Skip to content

Commit 0d92d2e

Browse files
chrisbobbegnprice
authored andcommitted
internalLinks: Parse '/dm/…' and '/is/dm' in narrow links
These are synonymous with '/pm-with/…' and '/is/private', respectively, and they'll start appearing in messages on newer servers, as part of the renaming of "private message" to "direct message". Mobile still generates links with the old '/pm-with/…' format in quote-and-reply. Those will still probably be supported indefinitely, but it'd be cleanest to switch to generating the new format, with a feature-level condition. Once the server/web-app merge code that uses the new format, we'll know what feature level to use. Fixes: #5692
1 parent 0c6b1c5 commit 0d92d2e

File tree

3 files changed

+49
-10
lines changed

3 files changed

+49
-10
lines changed

src/utils/__tests__/internalLinks-test.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ describe('isNarrowLink', () => {
4747
[true, 'with numeric stream ID', urlOnRealm('#narrow/stream/123-jest')],
4848
[true, 'with numeric stream ID and topic', urlOnRealm('#narrow/stream/123-jest/topic/topic1')],
4949

50-
[true, 'with numeric pm user IDs', urlOnRealm('#narrow/pm-with/123-mark')],
50+
[true, 'with numeric pm user IDs (new operator)', urlOnRealm('#narrow/dm/123-mark')],
51+
[true, 'with numeric pm user IDs (old operator)', urlOnRealm('#narrow/pm-with/123-mark')],
5152

5253
[false, 'wrong fragment', urlOnRealm('#nope')],
5354
[false, 'wrong path', urlOnRealm('/user_uploads/#narrow/stream/jest')],
@@ -183,6 +184,15 @@ describe('getNarrowFromNarrowLink (part 1)', () => {
183184
].forEach(hash => check(hash));
184185
});
185186

187+
describe('"/#narrow/dm/<…>" is a PM link', () => {
188+
const check = mkCheck(isPmNarrow);
189+
[
190+
'/#narrow/dm/1,2-group',
191+
'/#narrow/dm/1,2-group/near/1',
192+
'/#narrow/dm/a.40b.2Ecom.2Ec.2Ed.2Ecom/near/3',
193+
].forEach(hash => check(hash));
194+
});
195+
186196
describe('"/#narrow/pm-with/<…>" is a PM link', () => {
187197
const check = mkCheck(isPmNarrow);
188198
[
@@ -194,9 +204,12 @@ describe('getNarrowFromNarrowLink (part 1)', () => {
194204

195205
describe('"/#narrow/is/<…>" with valid operand is a special link', () => {
196206
const check = mkCheck(isSpecialNarrow);
197-
['/#narrow/is/private', '/#narrow/is/starred', '/#narrow/is/mentioned'].forEach(hash =>
198-
check(hash),
199-
);
207+
[
208+
'/#narrow/is/dm',
209+
'/#narrow/is/private',
210+
'/#narrow/is/starred',
211+
'/#narrow/is/mentioned',
212+
].forEach(hash => check(hash));
200213
});
201214

202215
describe('unexpected link shape gives null', () => {
@@ -375,6 +388,9 @@ describe('getNarrowFromNarrowLink (part 2)', () => {
375388

376389
test('on group PM link', () => {
377390
const ids = `${userB.user_id},${userC.user_id}`;
391+
expect(get(`https://example.com/#narrow/dm/${ids}-group`, [])).toEqual(
392+
pmNarrowFromUsersUnsafe([userB, userC]),
393+
);
378394
expect(get(`https://example.com/#narrow/pm-with/${ids}-group`, [])).toEqual(
379395
pmNarrowFromUsersUnsafe([userB, userC]),
380396
);
@@ -383,19 +399,26 @@ describe('getNarrowFromNarrowLink (part 2)', () => {
383399
test('on group PM link including self', () => {
384400
// The webapp doesn't generate these, but best to handle them anyway.
385401
const ids = `${eg.selfUser.user_id},${userB.user_id},${userC.user_id}`;
402+
expect(get(`https://example.com/#narrow/dm/${ids}-group`, [])).toEqual(
403+
pmNarrowFromUsersUnsafe([userB, userC]),
404+
);
386405
expect(get(`https://example.com/#narrow/pm-with/${ids}-group`, [])).toEqual(
387406
pmNarrowFromUsersUnsafe([userB, userC]),
388407
);
389408
});
390409

391410
test('on a special link', () => {
411+
expect(get('/#narrow/is/dm', [])).toEqual(ALL_PRIVATE_NARROW);
392412
expect(get('/#narrow/is/private', [])).toEqual(ALL_PRIVATE_NARROW);
393413
expect(get('/#narrow/is/starred', [])).toEqual(STARRED_NARROW);
394414
expect(get('/#narrow/is/mentioned', [])).toEqual(MENTIONED_NARROW);
395415
});
396416

397417
test('on a message link', () => {
398418
const ids = `${userB.user_id},${userC.user_id}`;
419+
expect(get(`https://example.com/#narrow/dm/${ids}-group/near/2`, [])).toEqual(
420+
pmNarrowFromUsersUnsafe([userB, userC]),
421+
);
399422
expect(get(`https://example.com/#narrow/pm-with/${ids}-group/near/2`, [])).toEqual(
400423
pmNarrowFromUsersUnsafe([userB, userC]),
401424
);
@@ -421,6 +444,7 @@ describe('getNearOperandFromLink', () => {
421444
});
422445

423446
test('when link is a group link, return anchor message id', () => {
447+
expect(getNearOperandFromLink(new URL('/#narrow/dm/1,3-group/near/1/', realm), realm)).toBe(1);
424448
expect(
425449
getNearOperandFromLink(new URL('/#narrow/pm-with/1,3-group/near/1/', realm), realm),
426450
).toBe(1);

src/utils/internalLinks.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,11 @@ export const getNarrowFromNarrowLink = (
144144
const hashSegments = getHashSegmentsFromNarrowLink(url, realm);
145145

146146
if (
147-
(hashSegments.length === 2 && hashSegments[0] === 'pm-with')
148-
|| (hashSegments.length === 4 && hashSegments[0] === 'pm-with' && hashSegments[2] === 'near')
147+
// 'dm' is new in server-7.0; means the same as 'pm-with'
148+
(hashSegments.length === 2 && (hashSegments[0] === 'pm-with' || hashSegments[0] === 'dm'))
149+
|| (hashSegments.length === 4
150+
&& (hashSegments[0] === 'pm-with' || hashSegments[0] === 'dm')
151+
&& hashSegments[2] === 'near')
149152
) {
150153
// TODO: This case is pretty useless in practice, due to basically a
151154
// bug in the webapp: the URL that appears in the location bar for a
@@ -175,9 +178,18 @@ export const getNarrowFromNarrowLink = (
175178
&& hashSegments[0] === 'is'
176179
&& (hashSegments[1] === 'starred'
177180
|| hashSegments[1] === 'mentioned'
181+
|| hashSegments[1] === 'dm' // new in server-7.0; means the same as 'private'
178182
|| hashSegments[1] === 'private')
179183
) {
180-
return specialNarrow(hashSegments[1]);
184+
switch (hashSegments[1]) {
185+
case 'starred':
186+
return specialNarrow('starred');
187+
case 'mentioned':
188+
return specialNarrow('mentioned');
189+
case 'dm':
190+
case 'private':
191+
return specialNarrow('dm');
192+
}
181193
}
182194

183195
return null; // TODO(?) Give HOME_NARROW

src/utils/narrow.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,13 @@ export const pmNarrowFromUsersUnsafe = (recipients: $ReadOnlyArray<UserOrBot>):
124124
export const pm1to1NarrowFromUser = (user: UserOrBot): Narrow =>
125125
pmNarrowInternal(pmKeyRecipientsFor1to1(user.user_id));
126126

127-
export const specialNarrow = (operand: 'starred' | 'mentioned' | 'private'): Narrow => {
127+
export const specialNarrow = (operand: 'starred' | 'mentioned' | 'dm'): Narrow => {
128128
switch (operand) {
129129
case 'starred':
130130
return Object.freeze({ type: 'starred' });
131131
case 'mentioned':
132132
return Object.freeze({ type: 'mentioned' });
133-
case 'private':
133+
case 'dm':
134134
return Object.freeze({ type: 'all-pm' });
135135
default:
136136
ensureUnreachable(operand);
@@ -146,7 +146,7 @@ export const MENTIONED_NARROW: Narrow = specialNarrow('mentioned');
146146

147147
export const MENTIONED_NARROW_STR: string = keyFromNarrow(MENTIONED_NARROW);
148148

149-
export const ALL_PRIVATE_NARROW: Narrow = specialNarrow('private');
149+
export const ALL_PRIVATE_NARROW: Narrow = specialNarrow('dm');
150150

151151
export const ALL_PRIVATE_NARROW_STR: string = keyFromNarrow(ALL_PRIVATE_NARROW);
152152

@@ -437,13 +437,16 @@ export const apiNarrowOfNarrow = (
437437
],
438438
pm: ids => {
439439
const emails = ids.map(id => get('user', allUsersById, id).email);
440+
// TODO(server-7.0): send `dm` rather than `pm-with`
440441
// TODO(server-2.1): just send IDs instead
441442
return [{ operator: 'pm-with', operand: emails.join(',') }];
442443
},
443444
search: query => [{ operator: 'search', operand: query }],
444445
home: () => [],
445446
starred: () => [{ operator: 'is', operand: 'starred' }],
446447
mentioned: () => [{ operator: 'is', operand: 'mentioned' }],
448+
449+
// TODO(server-7.0): send `is:dm` rather than `is:private`
447450
allPrivate: () => [{ operator: 'is', operand: 'private' }],
448451
});
449452
};

0 commit comments

Comments
 (0)