diff --git a/src/nav/AppNavigator.js b/src/nav/AppNavigator.js
index 442e5f775b1..8238ab9e770 100644
--- a/src/nav/AppNavigator.js
+++ b/src/nav/AppNavigator.js
@@ -184,7 +184,6 @@ export default function AppNavigator(props: Props): Node {
name="notif-troubleshooting"
component={useHaveServerDataGate(NotifTroubleshootingScreen)}
/>
-
@@ -205,6 +204,7 @@ export default function AppNavigator(props: Props): Node {
}
/>
+
);
diff --git a/src/settings/LegalScreen.js b/src/settings/LegalScreen.js
index 8cd7ef98735..0269bc58f07 100644
--- a/src/settings/LegalScreen.js
+++ b/src/settings/LegalScreen.js
@@ -3,56 +3,133 @@
import React, { useCallback } from 'react';
import type { Node } from 'react';
+import { createSelector } from 'reselect';
import type { RouteProp } from '../react-navigation';
import type { AppNavigationProp } from '../nav/AppNavigator';
-import { useGlobalSelector, useSelector } from '../react-redux';
+import { useGlobalSelector } from '../react-redux';
import Screen from '../common/Screen';
import NavRow from '../common/NavRow';
import ZulipText from '../common/ZulipText';
import { openLinkWithUserPreference } from '../utils/openLink';
-import { getRealmUrl, getRealmName, getGlobalSettings } from '../selectors';
+import { getRealmName, getGlobalSettings } from '../selectors';
+import { getAccounts } from '../directSelectors';
+import type { GlobalSelector } from '../reduxTypes';
+import { getAccount, tryGetActiveAccountState } from '../account/accountsSelectors';
+import { identityOfAccount, keyOfIdentity } from '../account/accountMisc';
+import { getHaveServerData } from '../haveServerDataSelectors';
+
+/**
+ * Data for all realms represented in `state.accounts`, logged-in or not,
+ * unique by URL.
+ *
+ * The realm name will be missing when we don't have server data for any
+ * account on the realm.
+ */
+type ViewModel = $ReadOnlyArray<{|
+ +realm: URL,
+ +name: string | null,
+ +policiesUrl: URL,
+|}>;
+
+const getViewModel: GlobalSelector = createSelector(
+ getAccounts,
+ tryGetActiveAccountState,
+ (accounts, activeAccountState) => {
+ const result = new Map(accounts.map(a => [a.realm.toString(), null]));
+
+ accounts.forEach(account => {
+ const realmStr = account.realm.toString();
+
+ if (result.get(realmStr) != null) {
+ return;
+ }
+
+ // TODO(#5006): Add realm name for any account we have server data for,
+ // not just the active account.
+ if (
+ activeAccountState
+ && keyOfIdentity(identityOfAccount(getAccount(activeAccountState)))
+ === keyOfIdentity(identityOfAccount(account))
+ && getHaveServerData(activeAccountState)
+ ) {
+ result.set(realmStr, getRealmName(activeAccountState));
+ }
+ });
+
+ return [...result.entries()].map(([realmStr, name]) => {
+ const realm = new URL(realmStr);
+ return {
+ realm,
+ name,
+ policiesUrl: new URL('/policies/?nav=no', realm),
+ };
+ });
+ },
+);
type Props = $ReadOnly<{|
navigation: AppNavigationProp<'legal'>,
route: RouteProp<'legal', void>,
|}>;
-/** (NB this is a per-account screen: it leads to this realm's policies.) */
+const zulipPoliciesUrl = new URL('https://zulip.com/policies/?nav=no');
+
+/**
+ * A global, all-accounts screen linking to terms for all realms we know about.
+ */
export default function LegalScreen(props: Props): Node {
- const realm = useSelector(getRealmUrl);
- const realmName = useSelector(getRealmName);
+ const viewModel = useGlobalSelector(getViewModel);
const globalSettings = useGlobalSelector(getGlobalSettings);
const openZulipPolicies = useCallback(() => {
- openLinkWithUserPreference(new URL('https://zulip.com/policies/?nav=no'), globalSettings);
+ openLinkWithUserPreference(zulipPoliciesUrl, globalSettings);
}, [globalSettings]);
- const openRealmPolicies = useCallback(() => {
- openLinkWithUserPreference(new URL('/policies/?nav=no', realm), globalSettings);
- }, [realm, globalSettings]);
-
return (
-
},
- }}
- onPress={openRealmPolicies}
+ title="Zulip terms"
+ subtitle={{ text: '{_}', values: { _: zulipPoliciesUrl.toString() } }}
+ onPress={openZulipPolicies}
type="external"
/>
+ {viewModel.map(({ realm, name, policiesUrl }) => (
+
+ ),
+ },
+ }}
+ subtitle={
+ // It's nice to be explicit about where the policies live,
+ // though the "?nav=no" is a bit annoying. But also, this line
+ // disambiguates multiple realms with the same name; the name is
+ // shown (when we have it) in `title`.
+ { text: '{_}', values: { _: policiesUrl.toString() } }
+ }
+ onPress={() => {
+ openLinkWithUserPreference(policiesUrl, globalSettings);
+ }}
+ type="external"
+ />
+ ))}
);
}