11/* @flow strict-local */
22// import { Vibration } from 'react-native';
3+ import { CommonActions } from '@react-navigation/native' ;
34
4- import type { ThunkAction } from '../types' ;
5+ import type { Narrow , ThunkAction } from '../types' ;
56import type { EventAction } from '../actionTypes' ;
6- import { EVENT_TYPING_START } from '../actionConstants' ;
7+ import { EVENT_TYPING_START , EVENT_UPDATE_MESSAGE } from '../actionConstants' ;
78import { ensureTypingStatusExpiryLoop } from '../typing/typingActions' ;
9+ import * as NavigationService from '../nav/NavigationService' ;
10+ import {
11+ isStreamNarrow ,
12+ isTopicNarrow ,
13+ streamIdOfNarrow ,
14+ topicNarrow ,
15+ topicOfNarrow ,
16+ } from '../utils/narrow' ;
817
918/**
1019 * React to actions dispatched for Zulip server events.
@@ -16,6 +25,63 @@ export default (action: EventAction): ThunkAction<Promise<void>> => async (dispa
1625 case EVENT_TYPING_START :
1726 dispatch ( ensureTypingStatusExpiryLoop ( ) ) ;
1827 break ;
28+
29+ case EVENT_UPDATE_MESSAGE : {
30+ // If the conversation we were looking at got moved, follow it.
31+ // See #5251 for background.
32+
33+ const { event, move } = action ;
34+ const { propagate_mode } = event ;
35+ if ( ! move || ! ( propagate_mode === 'change_all' || propagate_mode === 'change_later' ) ) {
36+ // This edit wasn't a move, or was targeted to a specific message.
37+ break ;
38+ }
39+
40+ const navState = NavigationService . getState ( ) ;
41+ for ( const route of navState . routes ) {
42+ if ( route . name !== 'chat' ) {
43+ continue ;
44+ }
45+
46+ // $FlowFixMe[incompatible-type]: relying on ChatScreen route-params type
47+ const narrow : Narrow = route . params ?. narrow ;
48+ if (
49+ isTopicNarrow ( narrow )
50+ && streamIdOfNarrow ( narrow ) === move . orig_stream_id
51+ && topicOfNarrow ( narrow ) === move . orig_topic
52+ ) {
53+ // A ChatScreen showing the very conversation that was moved.
54+
55+ // Change the ChatScreen's narrow to follow the move.
56+ //
57+ // Web does this only if the blue box is on one of the affected
58+ // messages, in case only some of the conversation was moved.
59+ // We don't have a blue box, but:
60+ // TODO: Ideally if the moved messages are all offscreen we'd skip this.
61+ NavigationService . dispatch ( {
62+ ...CommonActions . setParams ( {
63+ narrow : topicNarrow ( move . new_stream_id , move . new_topic ) ,
64+ } ) ,
65+ // Spreading the `setParams` action and adding `source` like
66+ // this is the documented way to specify a route (rather than
67+ // apply to the focused route):
68+ // https://reactnavigation.org/docs/5.x/navigation-actions#setparams
69+ source : route . key ,
70+ } ) ;
71+
72+ // TODO(#5251): If compose box is open and topic was resolved, warn.
73+ } else if ( isStreamNarrow ( narrow ) && streamIdOfNarrow ( narrow ) === move . orig_stream_id ) {
74+ // A ChatScreen showing the stream that contained the moved messages.
75+ //
76+ // TODO(#5251): Update topic input, if it matches. (If the stream
77+ // changed too, unclear what to do. Possibly change the
78+ // screen's narrow, as if narrowed to the moved topic?)
79+ }
80+ }
81+
82+ break ;
83+ }
84+
1985 default :
2086 }
2187} ;
0 commit comments