Skip to content

Commit 685401d

Browse files
committed
message: Add feature to view edit history.
Creates a component 'EditHistory' that renders a webview to show the edit history of a message. This webview is non-interactive - the user can select/copy message contents, but can not interact with them - like open links/navigate to narrows etc. Fixes: #4134
1 parent 0fa14b6 commit 685401d

File tree

5 files changed

+110
-1
lines changed

5 files changed

+110
-1
lines changed

src/message/EditHistory.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* @flow strict-local */
2+
3+
import React from 'react';
4+
import { View, Platform } from 'react-native';
5+
import { WebView } from 'react-native-webview';
6+
import type { NavigationScreenProp } from 'react-navigation';
7+
import type { Dispatch, Auth, ThemeName, UserOrBot } from '../types';
8+
import SpinningProgress from '../common/SpinningProgress';
9+
import type { MessageSnapshot } from '../api/modelTypes';
10+
import { connect } from '../react-redux';
11+
import { getAuth, getAllUsersById } from '../selectors';
12+
import { Screen } from '../common';
13+
import * as api from '../api';
14+
import editHistoryHtml from '../webview/html/editHistoryHtml';
15+
16+
type SelectorProps = {|
17+
auth: Auth,
18+
usersById: Map<number, UserOrBot>,
19+
|};
20+
21+
type Props = $ReadOnly<{|
22+
navigation: NavigationScreenProp<{ params: {| messageId: number, theme: ThemeName |} }>,
23+
24+
dispatch: Dispatch,
25+
...SelectorProps,
26+
|}>;
27+
28+
type State = $ReadOnly<{|
29+
messageHistory: MessageSnapshot[] | null,
30+
|}>;
31+
32+
class EditHistory extends React.Component<Props, State> {
33+
state = {
34+
messageHistory: null,
35+
};
36+
37+
async componentDidMount() {
38+
const { auth, navigation } = this.props;
39+
40+
this.setState({
41+
messageHistory: (await api.getMessageHistory(auth, navigation.state.params.messageId))
42+
.message_history,
43+
});
44+
}
45+
46+
render() {
47+
const { messageHistory } = this.state;
48+
49+
if (messageHistory === null) {
50+
return (
51+
<Screen title="Edit History">
52+
<View style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
53+
<SpinningProgress color="white" size={48} />
54+
</View>
55+
</Screen>
56+
);
57+
}
58+
const { usersById, auth } = this.props;
59+
const theme = this.props.navigation.state.params.theme;
60+
61+
// For the logic behind these, see comments in MessageList component's render method.
62+
const assetsPath = Platform.OS === 'ios' ? './webview' : 'file:///android_asset/webview';
63+
const baseUrl = `${assetsPath}/editHistory.html`;
64+
65+
const html: string = editHistoryHtml(messageHistory, theme, usersById, auth);
66+
67+
return (
68+
<Screen title="Edit History">
69+
<WebView
70+
source={{ baseUrl, html }}
71+
originWhitelist={['file://']}
72+
style={{ backgroundColor: 'transparent' }}
73+
onShouldStartLoadWithRequest={(_: string) => false} // Don't load any webview requests.
74+
onError={(msg: mixed) => {
75+
// eslint-disable-next-line no-console
76+
console.error(msg);
77+
}}
78+
/>
79+
</Screen>
80+
);
81+
}
82+
}
83+
84+
export default connect<SelectorProps, _, _>((state, props) => ({
85+
auth: getAuth(state),
86+
usersById: getAllUsersById(state),
87+
}))(EditHistory);

src/message/messageActionSheet.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { isTopicMuted } from '../utils/message';
2222
import * as api from '../api';
2323
import { showToast } from '../utils/info';
2424
import { doNarrow, deleteOutboxMessage, navigateToEmojiPicker } from '../actions';
25-
import { navigateToMessageReactionScreen } from '../nav/navActions';
25+
import { navigateToMessageReactionScreen, navigateToEditHistory } from '../nav/navActions';
2626
import { pmUiRecipientsFromMessage } from '../utils/recipient';
2727
import { deleteMessagesForTopic } from '../topics/topicActions';
2828
import * as logging from '../utils/logging';
@@ -41,6 +41,7 @@ type ButtonDescription = {
4141
ownEmail: string,
4242
message: Message | Outbox,
4343
subscriptions: Subscription[],
44+
backgroundData: BackgroundData,
4445
dispatch: Dispatch,
4546
_: GetText,
4647
startEditMessage: (editMessage: EditMessage) => void,
@@ -200,6 +201,12 @@ const showReactions = ({ message, dispatch }) => {
200201
showReactions.title = 'See who reacted';
201202
showReactions.errorMessage = 'Failed to show reactions';
202203

204+
const editHistory = ({ message, dispatch, backgroundData }) => {
205+
dispatch(navigateToEditHistory(message.id, backgroundData.theme));
206+
};
207+
editHistory.title = 'Show edit history';
208+
editHistory.errorMessage = 'Failed to show edit history';
209+
203210
const cancel = params => {};
204211
cancel.title = 'Cancel';
205212
cancel.errorMessage = 'Failed to hide menu';
@@ -215,6 +222,7 @@ const allButtonsRaw = {
215222
starMessage,
216223
unstarMessage,
217224
showReactions,
225+
editHistory,
218226

219227
// For headers
220228
unmuteTopic,
@@ -316,6 +324,11 @@ export const constructMessageActionButtons = ({
316324
} else {
317325
buttons.push('starMessage');
318326
}
327+
328+
if (message.last_edit_timestamp !== undefined) {
329+
buttons.push('editHistory');
330+
}
331+
319332
buttons.push('cancel');
320333
return buttons;
321334
};

src/nav/AppNavigator.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import TopicListScreen from '../topics/TopicListScreen';
3131
import EmojiPickerScreen from '../emoji/EmojiPickerScreen';
3232
import LegalScreen from '../settings/LegalScreen';
3333
import UserStatusScreen from '../user-status/UserStatusScreen';
34+
import EditHistory from '../message/EditHistory';
3435

3536
export default createStackNavigator(
3637
// $FlowFixMe react-navigation types :-/ -- see a36814e80
@@ -45,6 +46,7 @@ export default createStackNavigator(
4546
loading: { screen: LoadingScreen },
4647
main: { screen: MainScreenWithTabs },
4748
'message-reactions': { screen: MessageReactionList },
49+
'edit-history': { screen: EditHistory },
4850
password: { screen: PasswordAuthScreen },
4951
realm: { screen: RealmScreen },
5052
search: { screen: SearchMessagesScreen },

src/nav/navActions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
Narrow,
1010
UserOrBot,
1111
ApiResponseServerSettings,
12+
ThemeName,
1213
} from '../types';
1314
import { getSameRoutesCount } from '../selectors';
1415

@@ -99,6 +100,9 @@ export const navigateToMessageReactionScreen = (
99100
): NavigationAction =>
100101
StackActions.push({ routeName: 'message-reactions', params: { messageId, reactionName } });
101102

103+
export const navigateToEditHistory = (messageId: number, theme: ThemeName): NavigationAction =>
104+
StackActions.push({ routeName: 'edit-history', params: { messageId, theme } });
105+
102106
export const navigateToLegal = (): NavigationAction => StackActions.push({ routeName: 'legal' });
103107

104108
export const navigateToUserStatus = (): NavigationAction =>

static/translations/messages_en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@
139139
"Share": "Share",
140140
"Star message": "Star message",
141141
"Unstar message": "Unstar message",
142+
"Show edit history": "Show edit history",
143+
"Failed to show edit history": "Failed to show edit history",
142144
"Cancel": "Cancel",
143145
"Message copied": "Message copied",
144146
"Edit message": "Edit message",
@@ -187,6 +189,7 @@
187189
"Please download the image from your browser": "Please download the image from your browser",
188190
"Can not download": "Can not download",
189191
"Download file": "Download file",
192+
"Edit History": "Edit History",
190193
"Update": "Update",
191194
"Save": "Save",
192195
"Pinned": "Pinned",

0 commit comments

Comments
 (0)