Skip to content

Commit 7d207b8

Browse files
committed
messages state: Keep edit_history null if allowEditHistory is false
1 parent 6ec2865 commit 7d207b8

File tree

9 files changed

+69
-27
lines changed

9 files changed

+69
-27
lines changed

src/api/messages/__tests__/migrateMessages-test.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ describe('recent server', () => {
6262
input,
6363
identityOfAuth(eg.selfAuth),
6464
eg.recentZulipFeatureLevel,
65+
true,
6566
);
6667

6768
test('In reactions, replace user object with `user_id`', () => {
@@ -72,9 +73,17 @@ describe('recent server', () => {
7273
expect(actualOutput.map(m => m.avatar_url)).toEqual(expectedOutput.map(m => m.avatar_url));
7374
});
7475

75-
test('Keeps edit_history', () => {
76+
test('Keeps edit_history, if allowEditHistory is true', () => {
7677
expect(actualOutput.map(m => m.edit_history)).toEqual(expectedOutput.map(m => m.edit_history));
7778
});
79+
80+
test('Drops edit_history, if allowEditHistory is false', () => {
81+
expect(
82+
migrateMessages(input, identityOfAuth(eg.selfAuth), eg.recentZulipFeatureLevel, false).map(
83+
m => m.edit_history,
84+
),
85+
).toEqual(expectedOutput.map(m => null));
86+
});
7887
});
7988

8089
describe('drops edit_history from pre-118 server', () => {
@@ -97,6 +106,7 @@ describe('drops edit_history from pre-118 server', () => {
97106
],
98107
identityOfAuth(eg.selfAuth),
99108
117,
109+
true,
100110
).map(m => m.edit_history),
101111
).toEqual([null]);
102112
});

src/api/messages/getMessages.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export const migrateMessages = (
7979
messages: $ReadOnlyArray<ServerMessage>,
8080
identity: Identity,
8181
zulipFeatureLevel: number,
82+
allowEditHistory: boolean,
8283
): Message[] =>
8384
messages.map(<M: Message>(message: ServerMessageOf<M>): M => ({
8485
...message,
@@ -95,20 +96,22 @@ export const migrateMessages = (
9596
user_id: user.id,
9697
};
9798
}),
99+
100+
// Why condition on allowEditHistory? See MessageBase['edit_history'].
98101
// Why FL 118 condition? See MessageEdit type.
99102
edit_history:
100103
/* eslint-disable operator-linebreak */
101-
zulipFeatureLevel >= 118
104+
allowEditHistory && zulipFeatureLevel >= 118
102105
? // $FlowIgnore[incompatible-cast] - See MessageEdit type
103106
(message.edit_history: $ReadOnlyArray<MessageEdit> | void)
104107
: null,
105108
}));
106109

107-
const migrateResponse = (response, identity: Identity, zulipFeatureLevel) => {
110+
const migrateResponse = (response, identity: Identity, zulipFeatureLevel, allowEditHistory) => {
108111
const { messages, ...restResponse } = response;
109112
return {
110113
...restResponse,
111-
messages: migrateMessages(messages, identity, zulipFeatureLevel),
114+
messages: migrateMessages(messages, identity, zulipFeatureLevel, allowEditHistory),
112115
};
113116
};
114117

@@ -127,6 +130,9 @@ export default async (
127130

128131
// TODO(#4659): Don't get this from callers.
129132
zulipFeatureLevel: number,
133+
134+
// TODO(#4659): Don't get this from callers?
135+
allowEditHistory: boolean,
130136
): Promise<ApiResponseMessages> => {
131137
const { narrow, anchor, numBefore, numAfter, useFirstUnread = false } = args;
132138
const response: ServerApiResponseMessages = await apiGet(auth, 'messages', {
@@ -138,5 +144,5 @@ export default async (
138144
use_first_unread_anchor: useFirstUnread,
139145
client_gravatar: true,
140146
});
141-
return migrateResponse(response, identityOfAuth(auth), zulipFeatureLevel);
147+
return migrateResponse(response, identityOfAuth(auth), zulipFeatureLevel, allowEditHistory);
142148
};

src/api/modelTypes.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -750,22 +750,17 @@ type MessageBase = $ReadOnly<{|
750750
// display_recipient handled on PmMessage and StreamMessage separately
751751

752752
/**
753-
* A possibly incomplete view of the message's edit history.
753+
* A view of the message's edit history, if available.
754754
*
755755
* This is null if it's coming from a server with FL <118; see comment on
756756
* MessageEdit.
757757
*
758+
* Null if the realm doesn't allow viewing edit history.
759+
*
758760
* Missing/undefined if the message had no edit history when we added it
759761
* to the state.
760-
*
761-
* Missing/undefined if, at the time we added it to the state, the realm
762-
* didn't allow viewing edit history.
763762
*/
764-
// TODO: Keep reasonably current:
765-
// - Use `null` for the `allow_edit_history`-false case, to distinguish it
766-
// from the message-never-edited case. (Handle everywhere we add/update
767-
// Messages in Redux: the get-messages response, new-message events,
768-
// update-message events.)
763+
// TODO: Keep current:
769764
// - Handle changes to the allow_edit_history setting:
770765
// - Treat an allow_edit_history change similar to a restart event (in
771766
// particular, a restart event where the server version changed, which
@@ -775,8 +770,7 @@ type MessageBase = $ReadOnly<{|
775770
// TODO(server-5.0): Remove FL <118 condition
776771
//
777772
// (Why optional and `| void`? We convert missing to undefined at the
778-
// edge, while doing the FL <118 condition, but that's incidental and
779-
// could easily change.)
773+
// edge, but that's incidental and could easily change.)
780774
edit_history?: $ReadOnlyArray<MessageEdit> | null | void,
781775

782776
id: number,

src/events/__tests__/eventToAction-test.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,26 @@ describe('eventToAction', () => {
7575
expect(action.message.avatar_url).toBeInstanceOf(AvatarURL);
7676
});
7777

78-
test('Keeps edit_history', () => {
78+
test('Keeps edit_history if allowEditHistory is true', () => {
79+
// eslint-disable-next-line no-shadow
80+
const action = eventToAction(
81+
eg.reduxStatePlus({ realm: { ...eg.plusReduxState.realm, allowEditHistory: true } }),
82+
event,
83+
);
84+
invariant(actionMatchesType(action, EVENT_NEW_MESSAGE), 'EVENT_NEW_MESSAGE produced');
7985
expect(action.message.edit_history).not.toBeNull();
8086
expect(action.message.edit_history).toEqual(serverMessage.edit_history);
8187
});
88+
89+
test('Drops edit_history if allowEditHistory is false', () => {
90+
// eslint-disable-next-line no-shadow
91+
const action = eventToAction(
92+
eg.reduxStatePlus({ realm: { ...eg.plusReduxState.realm, allowEditHistory: false } }),
93+
event,
94+
);
95+
invariant(actionMatchesType(action, EVENT_NEW_MESSAGE), 'EVENT_NEW_MESSAGE produced');
96+
expect(action.message.edit_history).toBeNull();
97+
});
8298
});
8399

84100
describe('edit_history for FL <118', () => {

src/events/eventToAction.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
EVENT_SUBSCRIPTION,
3232
EVENT,
3333
} from '../actionConstants';
34+
import { getRealm } from '../selectors';
3435
import { getOwnUserId, tryGetUserForId } from '../users/userSelectors';
3536
import { AvatarURL } from '../utils/avatar';
3637
import { getRealmUrl, getZulipFeatureLevel } from '../account/accountsSelectors';
@@ -91,6 +92,8 @@ const actionTypeOfEventType = {
9192
// assumptions about the events the server sends, and doesn't check them.
9293
export default (state: PerAccountState, event: $FlowFixMe): EventAction | null => {
9394
const zulipFeatureLevel = getZulipFeatureLevel(state);
95+
const allowEditHistory = getRealm(state).allowEditHistory;
96+
9497
const type = (event.type: EventType);
9598
switch (type) {
9699
// For reference on each type of event, see:
@@ -118,8 +121,9 @@ export default (state: PerAccountState, event: $FlowFixMe): EventAction | null =
118121
realm: getRealmUrl(state),
119122
}),
120123
edit_history:
124+
// Why condition on allowEditHistory? See MessageBase['edit_history'].
121125
// Why FL 118 condition? See MessageEdit type.
122-
zulipFeatureLevel >= 118
126+
allowEditHistory && zulipFeatureLevel >= 118
123127
? (event.message.edit_history: $ReadOnlyArray<MessageEdit> | void)
124128
: null,
125129
},

src/message/__tests__/fetchActions-test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ describe('fetchActions', () => {
254254
narrows: Immutable.Map({
255255
[streamNarrowStr]: [message1.id],
256256
}),
257+
realm: {
258+
...eg.plusReduxState.realm,
259+
allowEditHistory: true, // TODO: test with this `false`
260+
},
257261
});
258262

259263
describe('success', () => {

src/message/__tests__/messagesReducer-test.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ describe('messagesReducer', () => {
792792
],
793793
};
794794

795-
test('on never-edited message, or one received with realm_allow_edit_history: false, creates one-item array', () => {
795+
test('on never-edited message, creates one-item array', () => {
796796
expect(
797797
messagesReducer(
798798
eg.makeMessagesState([afterNoUpdates]),
@@ -809,8 +809,7 @@ describe('messagesReducer', () => {
809809
});
810810
});
811811

812-
// TODO(server-5.0): Simplify away.
813-
test("don't touch it if we dropped it because server was FL <118", () => {
812+
test("don't touch it if we dropped it", () => {
814813
const message1Old = eg.streamMessage({
815814
content: '<p>Old content</p>',
816815
subject: 'Old topic',

src/message/fetchActions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as api from '../api';
1414
import { Server5xxError, NetworkError } from '../api/apiErrors';
1515
import {
1616
getAuth,
17+
getRealm,
1718
getSession,
1819
getFirstMessageId,
1920
getLastMessageId,
@@ -113,6 +114,7 @@ export const fetchMessages =
113114
useFirstUnread: fetchArgs.anchor === FIRST_UNREAD_ANCHOR, // TODO: don't use this; see #4203
114115
},
115116
getZulipFeatureLevel(getState()),
117+
getRealm(getState()).allowEditHistory,
116118
),
117119
);
118120
dispatch(
@@ -223,6 +225,7 @@ export async function fetchSomeMessageIdForConversation(
223225
narrow: apiNarrowOfNarrow(topicNarrow(streamId, topic), new Map(), streamsById),
224226
},
225227
zulipFeatureLevel,
228+
false, // chosen arbitrarily; irrelevant to this function's task
226229
);
227230
// FlowIssue: can be void because array can be empty
228231
const message: Message | void = data.messages[0];
@@ -308,6 +311,7 @@ export const fetchPrivateMessages =
308311
numAfter: 0,
309312
},
310313
getZulipFeatureLevel(getState()),
314+
getRealm(getState()).allowEditHistory,
311315
);
312316
dispatch(
313317
messageFetchComplete({

src/message/messagesReducer.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,17 @@ const editHistory = <M: Message>(args: {|
8181
|}) => {
8282
const { oldMessage, event, move, shouldApplyContentChanges } = args;
8383
if (oldMessage.edit_history === null) {
84-
// We ignored a maybe-interesting `edit_history` when we learned about
85-
// the message because the value wouldn't have been in a nice shape; see
86-
// Message['edit_history']. Keep ignoring it; don't give it a partial
87-
// value, such as a one-item array based on this edit, which would be
88-
// corrupt.
89-
// TODO(server-5.0): Simplify away.
84+
// Either:
85+
// - we dropped edit_history because the server was old and the value
86+
// wouldn't have been in a nice shape, or
87+
// - the realm is set to not allow viewing edit history
88+
//
89+
// (See Message['edit_history'].) Keep maintaining nothing here; don't
90+
// write a partial value, such as a one-item array based on this edit,
91+
// which would be corrupt.
92+
//
93+
// TODO(server-5.0): Simplify away the FL condition; keep the
94+
// allowEditHistory condition.
9095
return null;
9196
}
9297

0 commit comments

Comments
 (0)