Skip to content

Commit 2d3ddcf

Browse files
authored
Merge branch 'zulip:main' into main
2 parents 333fd1e + fccfa23 commit 2d3ddcf

File tree

8 files changed

+71
-79
lines changed

8 files changed

+71
-79
lines changed

LICENSE

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,3 @@
1-
Copyright 2016-2018 Kandra Labs, Inc., and contributors
2-
3-
Licensed under the Apache License, Version 2.0 (the "License");
4-
you may not use this software except in compliance with the License.
5-
You may obtain a copy of the License at
6-
7-
http://www.apache.org/licenses/LICENSE-2.0
8-
9-
Unless required by applicable law or agreed to in writing, software
10-
distributed under the License is distributed on an "AS IS" BASIS,
11-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
See the License for the specific language governing permissions and
13-
limitations under the License.
14-
15-
The software includes some works released by third parties under other
16-
free and open source licenses. Those works are redistributed under the
17-
license terms under which the works were received. For more details,
18-
see the ``docs/THIRDPARTY`` file included with this distribution.
19-
20-
--------------------------------------------------------------------------------
211

222
Apache License
233
Version 2.0, January 2004

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Zulip Mobile supersedes two legacy Zulip apps,
8585

8686
## License
8787

88-
Copyright (c) 2016-2018 Kandra Labs, Inc., and contributors, and 2016 Dropbox, Inc.
88+
Copyright (c) 2016-2022 Kandra Labs, Inc., and contributors, and 2016 Dropbox, Inc.
8989

9090
Licensed under the Apache License, Version 2.0 (the "License");
9191
you may not use this file except in compliance with the License.

android/app/build.gradle

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,24 @@ repositories {
194194
}
195195

196196
dependencies {
197-
implementation fileTree(dir: "libs", include: ["*.jar"])
198197
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
198+
199199
implementation "androidx.core:core-ktx:1.7.0"
200200
implementation 'androidx.appcompat:appcompat:1.0.0'
201-
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
201+
implementation 'androidx.browser:browser:1.0.0'
202+
202203
implementation "com.google.firebase:firebase-messaging:17.3.4"
203-
//noinspection GradleDynamicVersion
204-
implementation "com.facebook.react:react-native:+" // From node_modules
204+
205+
// ==== Test dependencies
206+
testImplementation 'junit:junit:4.12'
207+
testImplementation 'org.junit.jupiter:junit-jupiter:5.4.0'
208+
testImplementation 'com.google.truth:truth:0.43'
209+
testImplementation 'com.google.truth.extensions:truth-java8-extension:0.43'
210+
testImplementation 'org.mockito:mockito-core:1.10.19'
211+
212+
// ==== RN-related dependencies
213+
214+
implementation 'com.facebook.fresco:animated-gif:2.0.0' // For animated GIF support
205215

206216
// Workaround for facebook/react-native#32735; see
207217
// https://github.com/facebook/react-native/issues/32735#issue-1077061487
@@ -212,6 +222,15 @@ dependencies {
212222
}
213223
}
214224

225+
// ----------------------------------------
226+
// Dependencies from RN upstream, in the template app
227+
228+
implementation fileTree(dir: "libs", include: ["*.jar"])
229+
//noinspection GradleDynamicVersion
230+
implementation "com.facebook.react:react-native:+" // From node_modules
231+
232+
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
233+
215234
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
216235
exclude group: 'com.facebook.fbjni'
217236
}
@@ -232,15 +251,10 @@ dependencies {
232251
} else {
233252
implementation jscFlavor
234253
}
254+
// END dependencies from RN upstream
255+
// ----------------------------------------
235256

236-
implementation 'com.facebook.fresco:animated-gif:2.0.0' // For animated GIF support
237-
implementation 'androidx.browser:browser:1.0.0'
238-
239-
testImplementation 'junit:junit:4.12'
240-
testImplementation 'org.junit.jupiter:junit-jupiter:5.4.0'
241-
testImplementation 'com.google.truth:truth:0.43'
242-
testImplementation 'com.google.truth.extensions:truth-java8-extension:0.43'
243-
testImplementation 'org.mockito:mockito-core:1.10.19'
257+
// Don't put new dependencies down here. Put them above, before the upstream section.
244258
}
245259

246260
// The default kotlinOptions.jvmTarget is 1.6. With the default, we get

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "ZulipMobile",
33
"version": "1.0.0",
4+
"license": "Apache-2.0",
45
"private": true,
56
"scripts": {
67
"postinstall": "bash tools/postinstall",

src/account/accountActions.js

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
/* @flow strict-local */
22
import * as NavigationService from '../nav/NavigationService';
3-
import type {
4-
Dispatch,
5-
PerAccountAction,
6-
AllAccountsAction,
7-
ThunkAction,
8-
GlobalThunkAction,
9-
} from '../types';
3+
import type { PerAccountAction, AllAccountsAction, ThunkAction, GlobalThunkAction } from '../types';
104
import {
115
ACCOUNT_SWITCH,
126
ACCOUNT_REMOVE,
@@ -34,30 +28,13 @@ const accountSwitchPlain = (index: number): AllAccountsAction => ({
3428

3529
export const accountSwitch =
3630
(index: number): GlobalThunkAction<Promise<void>> =>
37-
async (dispatch, getState) => {
31+
async (dispatch, getState, { activeAccountDispatch }) => {
3832
NavigationService.dispatch(resetToMainTabs());
3933
dispatch(accountSwitchPlain(index));
4034

41-
/* $FlowFixMe[incompatible-type]
42-
43-
This is really a GlobalDispatch, because we're in a GlobalThunkAction.
44-
(It's global because it needs to know about all the accounts to set the
45-
pointer to the active one). But here, we pretend it's a Dispatch.
46-
That's OK, for now, because:
47-
48-
- Our Dispatch function is secretly the same value as our
49-
GlobalDispatch.
50-
- The PerAccountState that Dispatch currently acts on is the one
51-
belonging to the active account.
52-
- We want this dispatch to act on the active account -- the new,
53-
post-switch active account.
54-
- It will act on that account, because at this point we've already
55-
dispatched `accountSwitchPlain`.
56-
57-
TODO(#5006): perhaps have an `activeAccountDispatch: Dispatch` in
58-
a new GlobalThunkExtras, modeled on ThunkExtras?
59-
*/
60-
const activeAccountDispatch: Dispatch = dispatch;
35+
// Now dispatch some actions on the new, post-switch active account.
36+
// Because we just dispatched `accountSwitchPlain`, that new account
37+
// is now the active account, so `activeAccountDispatch` will act on it.
6138

6239
await activeAccountDispatch(registerAndStartPolling());
6340

src/boot/store.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import CompressedAsyncStorage from '../storage/CompressedAsyncStorage';
2020
import createMigration from '../redux-persist-migrate/index';
2121
import { getGlobalSession, getGlobalSettings } from '../directSelectors';
2222
import { migrations } from '../storage/migrations';
23+
import type { Dispatch, GlobalThunkExtras } from '../reduxTypes';
2324

2425
if (process.env.NODE_ENV === 'development') {
2526
// Chrome dev tools for Immutable.
@@ -72,14 +73,35 @@ export const cacheKeys: $ReadOnlyArray<$Keys<GlobalState>> = [
7273
'realm', 'streams', 'subscriptions', 'unread', 'userGroups', 'users',
7374
];
7475

75-
const thunkExtras: ThunkExtras = {
76-
// eslint-disable-next-line no-use-before-define
77-
getGlobalSession: () => getGlobalSession(store.getState()),
76+
/* eslint-disable no-use-before-define */
7877

79-
// eslint-disable-next-line no-use-before-define
78+
const thunkExtras: $Exact<ThunkExtras> = {
79+
getGlobalSession: () => getGlobalSession(store.getState()),
8080
getGlobalSettings: () => getGlobalSettings(store.getState()),
8181
};
8282

83+
const globalThunkExtras: $Exact<GlobalThunkExtras> = {
84+
// $FlowFixMe[escaped-generic]
85+
// $FlowFixMe[incompatible-type]
86+
/* $FlowFixMe[incompatible-cast]
87+
The `store` type isn't complete: in particular it ignores thunk actions.
88+
89+
We're also using here the fact that the one function `store.dispatch`
90+
secretly plays both the role of our `GlobalDispatch` type and our
91+
`Dispatch` type... and that in the latter role, the PerAccountState
92+
that it acts on is the one belonging to the active account.
93+
94+
TODO(#5006): We'll have to add more logic here when per-account and
95+
global state become distinct.
96+
*/
97+
activeAccountDispatch: action => (store.dispatch: Dispatch)(action),
98+
};
99+
100+
const combinedThunkExtras: ThunkExtras & GlobalThunkExtras = {
101+
...thunkExtras,
102+
...globalThunkExtras,
103+
};
104+
83105
/**
84106
* Return a list of Redux middleware objects to use in our Redux store.
85107
*
@@ -97,7 +119,7 @@ function listMiddleware() {
97119
// Handle the fancy "thunk" actions we often use, i.e. async
98120
// functions of `dispatch` and `state`. See docs:
99121
// https://github.com/reduxjs/redux-thunk
100-
thunkMiddleware.withExtraArgument(thunkExtras),
122+
thunkMiddleware.withExtraArgument(combinedThunkExtras),
101123
];
102124

103125
if (config.enableReduxLogging) {

src/notification/notifOpen.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ const readInitialNotification = async (): Promise<Notification | null> => {
195195

196196
export const narrowToNotification =
197197
(data: ?Notification): GlobalThunkAction<void> =>
198-
(dispatch, getState) => {
198+
(dispatch, getState, { activeAccountDispatch }) => {
199199
if (!data) {
200200
return;
201201
}
@@ -228,15 +228,7 @@ export const narrowToNotification =
228228
getOwnUserId(state),
229229
);
230230
if (narrow) {
231-
// We have a GlobalDispatch, because this is a global thunk action --
232-
// at the top of the function, we didn't yet know which account was
233-
// intended and had to work that out. But now we know we're working on
234-
// the active account, and want to dispatch a per-account action there.
235-
// For the present, we just use the fact that our GlobalDispatch value
236-
// is the same function as we use for Dispatch.
237-
// TODO(#5006): perhaps have an `activeAccountDispatch: Dispatch` in a
238-
// new GlobalThunkExtras, modeled on ThunkExtras?
239-
(dispatch: $FlowFixMe)(doNarrow(narrow));
231+
activeAccountDispatch(doNarrow(narrow));
240232
}
241233
};
242234

src/reduxTypes.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,21 +636,27 @@ export interface Dispatch {
636636
/** A per-account thunk action returning T. */
637637
export type ThunkAction<T> = (Dispatch, () => PerAccountState, ThunkExtras) => T;
638638

639+
/** The extras object passed to a global thunk action. */
640+
export type GlobalThunkExtras = $ReadOnly<{
641+
/** A per-account `dispatch` that acts on the active account. */
642+
activeAccountDispatch: Dispatch,
643+
...
644+
}>;
645+
639646
/** The Redux `dispatch` for a global context. */
640647
export interface GlobalDispatch {
641648
<A: DispatchableWithoutAccountAction>(action: A): A;
642649
<T>(GlobalThunkAction<T>): T;
643650
}
644651

645652
/** A global thunk action returning T. */
646-
// This might take some extras later (e.g., to do something per-account on a
647-
// specific account), but for now it needs none.
648-
export type GlobalThunkAction<T> = (GlobalDispatch, () => GlobalState) => T;
653+
export type GlobalThunkAction<T> = (GlobalDispatch, () => GlobalState, GlobalThunkExtras) => T;
649654

650655
// The two pairs of dispatch/thunk-action types aren't interchangeable,
651656
// in either direction.
652657
// $FlowExpectedError[incompatible-return]
653658
(d: GlobalDispatch): Dispatch => d;
659+
// $FlowExpectedError[prop-missing]
654660
// $FlowExpectedError[incompatible-return]
655661
<T>(a: ThunkAction<T>): GlobalThunkAction<T> => a;
656662
// $FlowExpectedError[incompatible-return]

0 commit comments

Comments
 (0)