Skip to content

Commit

Permalink
notifications: Add button for test notification
Browse files Browse the repository at this point in the history
Tested on the office Android device, and on my iPhone.

For the iOS testing, I set up a dev server to talk directly to
Apple's APNs "sandbox" server, with our documented instructions:
  https://github.com/zulip/zulip-mobile/blob/main/docs/howto/push-notifications.md#testing-client-side-changes-on-ios

(I already had the relevant certificate, so I didn't need to go
through the steps with a certificate signing request.)

Fixes: zulip#5796
  • Loading branch information
chrisbobbe committed Dec 6, 2023
1 parent a424262 commit 9da79ed
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 3 deletions.
81 changes: 78 additions & 3 deletions src/settings/PerAccountNotificationSettingsGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ import { getAuth, getSettings } from '../selectors';
import SwitchRow from '../common/SwitchRow';
import * as api from '../api';
import NavRow from '../common/NavRow';
import TextRow from '../common/TextRow';
import { IconAlertTriangle } from '../common/Icons';
import { kWarningColor } from '../styles/constants';
import { getIdentity } from '../account/accountsSelectors';
import { getGlobalSettings, getRealm, getRealmName } from '../directSelectors';
import { getIdentity, getZulipFeatureLevel } from '../account/accountsSelectors';
import { getGlobalSession, getGlobalSettings, getRealm, getRealmName } from '../directSelectors';
import ZulipText from '../common/ZulipText';
import SettingsGroup from './SettingsGroup';
import { openLinkWithUserPreference } from '../utils/openLink';
import { useNotificationReportsByIdentityKey } from './NotifTroubleshootingScreen';
import { keyOfIdentity } from '../account/accountMisc';
import { getOwnUserRole, roleIsAtLeast } from '../permissionSelectors';
import { Role } from '../api/permissionsTypes';
import { ApiError } from '../api/apiErrors';
import { showErrorAlert } from '../utils/info';
import * as logging from '../utils/logging';
import { TranslationContext } from '../boot/TranslationProvider';

type Props = $ReadOnly<{|
navigation: AppNavigationMethods,
Expand All @@ -32,6 +37,8 @@ type Props = $ReadOnly<{|
export default function PerAccountNotificationSettingsGroup(props: Props): Node {
const { navigation } = props;

const _ = React.useContext(TranslationContext);

const auth = useSelector(getAuth);
const identity = useSelector(getIdentity);
const notificationReportsByIdentityKey = useNotificationReportsByIdentityKey();
Expand All @@ -41,6 +48,7 @@ export default function PerAccountNotificationSettingsGroup(props: Props): Node
'NotificationsScreen: expected notificationReport for current account',
);
const realmName = useSelector(getRealmName);
const zulipFeatureLevel = useSelector(getZulipFeatureLevel);
const pushNotificationsEnabled = useSelector(state => getRealm(state).pushNotificationsEnabled);
const isAtLeastAdmin = useSelector(state => roleIsAtLeast(getOwnUserRole(state), Role.Admin));
const offlineNotification = useSelector(state => getSettings(state).offlineNotification);
Expand All @@ -49,6 +57,11 @@ export default function PerAccountNotificationSettingsGroup(props: Props): Node

const globalSettings = useGlobalSelector(getGlobalSettings);

const pushToken = useGlobalSelector(state => getGlobalSession(state).pushToken);

// Helper variable so that we can refer to the button correctly in
// other UI text.
const troubleshootingPageTitle = 'Troubleshooting';
const handleTroubleshootingPress = useCallback(() => {
navigation.push('notif-troubleshooting');
}, [navigation]);
Expand Down Expand Up @@ -80,6 +93,62 @@ export default function PerAccountNotificationSettingsGroup(props: Props): Node
});
}, [streamNotification, auth]);

const [testNotificationRequestInProgress, setTestNotificationRequestInProgress] =
React.useState(false);
const handleTestNotificationPress = React.useCallback(async () => {
invariant(pushToken != null, 'should be disabled if pushToken missing');
setTestNotificationRequestInProgress(true);
try {
await api.sendTestNotification(auth, { token: pushToken });
} catch (errorIllTyped) {
const error: mixed = errorIllTyped; // https://github.com/facebook/flow/issues/2470

if (!(error instanceof Error)) {
logging.error('Unexpected non-error thrown from api.sendTestNotification');
return;
}

let msg = undefined;
if (error instanceof ApiError) {
// TODO recognize error.code and try to fix? give better feedback?
msg = _('The server said:\n\n{errorMessage}', { errorMessage: error.message });
} else if (error.message.length > 0) {
msg = error.message;
}
showErrorAlert(_('Failed to send test notification'), msg);
} finally {
setTestNotificationRequestInProgress(false);
}
}, [_, auth, pushToken]);

let testNotificationDisabled = false;
if (zulipFeatureLevel < 217) {
testNotificationDisabled = {
title: 'Server upgrade required',
message: {
text: 'This feature requires {zulipServerVersion} or higher.',
values: { zulipServerVersion: 'Zulip Server 8' },
},
learnMoreButton: {
url: new URL('https://zulip.readthedocs.io/en/latest/production/upgrade.html'),
text: 'How to upgrade (for server administrators)',
},
};
} else if (pushToken == null) {
testNotificationDisabled = {
title: 'Cannot send test notification',
message: {
text: 'Please tap “{troubleshootingPageTitle}” for more details.',
values: { troubleshootingPageTitle: _(troubleshootingPageTitle) },
},
};
} else if (testNotificationRequestInProgress) {
testNotificationDisabled = {
title: 'Request in progress',
message: 'Please wait. A request is already in progress.',
};
}

const children = pushNotificationsEnabled
? [
<SwitchRow
Expand Down Expand Up @@ -111,9 +180,15 @@ export default function PerAccountNotificationSettingsGroup(props: Props): Node
},
subtitle: 'Notifications for this account may not arrive.',
})()}
title="Troubleshooting"
title={troubleshootingPageTitle}
onPress={handleTroubleshootingPress}
/>,
<TextRow
key="test"
title="Send a test notification"
onPress={handleTestNotificationPress}
disabled={testNotificationDisabled}
/>,
]
: [
<NavRow
Expand Down
9 changes: 9 additions & 0 deletions static/translations/messages_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,15 @@
"Delete message": "Delete message",
"System settings for Zulip": "System settings for Zulip",
"Troubleshooting": "Troubleshooting",
"Send a test notification": "Send a test notification",
"Failed to send test notification": "Failed to send test notification",
"Server upgrade required": "Server upgrade required",
"This feature requires {zulipServerVersion} or higher.": "This feature requires {zulipServerVersion} or higher.",
"How to upgrade (for server administrators)": "How to upgrade (for server administrators)",
"Cannot send test notification": "Cannot send test notification",
"Please tap “{troubleshootingPageTitle}” for more details.": "Please tap “{troubleshootingPageTitle}” for more details.",
"Request in progress": "Request in progress",
"Please wait. A request is already in progress.": "Please wait. A request is already in progress.",
"Email {supportEmail}": "Email {supportEmail}",
"Draft saved": "Draft saved",
"Email sent": "Email sent",
Expand Down

0 comments on commit 9da79ed

Please sign in to comment.