Page MenuHomePhabricator

D12539.id41716.diff
No OneTemporary

D12539.id41716.diff

diff --git a/keyserver/src/creators/message-creator.js b/keyserver/src/creators/message-creator.js
--- a/keyserver/src/creators/message-creator.js
+++ b/keyserver/src/creators/message-creator.js
@@ -446,7 +446,7 @@
messageInfos,
messageDatas,
threadsToMessageIndices,
- preUserPushInfo.notFocusedThreadIDs,
+ [...preUserPushInfo.notFocusedThreadIDs],
userNotMemberOfSubthreads,
(messageID: string) => fetchMessageInfoByID(viewer, messageID),
userID,
@@ -457,7 +457,7 @@
messageInfos,
messageDatas,
threadsToMessageIndices,
- preUserPushInfo.notFocusedThreadIDs,
+ [...preUserPushInfo.notFocusedThreadIDs],
userNotMemberOfSubthreads,
(messageID: string) => fetchMessageInfoByID(viewer, messageID),
userID,
diff --git a/keyserver/src/push/send.js b/keyserver/src/push/send.js
--- a/keyserver/src/push/send.js
+++ b/keyserver/src/push/send.js
@@ -20,7 +20,11 @@
} from 'lib/push/android-notif-creators.js';
import { apnMaxNotificationPayloadByteSize } from 'lib/push/apns-notif-creators.js';
import type { PushUserInfo, PushInfo } from 'lib/push/send-utils.js';
-import { stringToVersionKey, getDevicesByPlatform } from 'lib/push/utils.js';
+import {
+ stringToVersionKey,
+ getDevicesByPlatform,
+ userAllowsNotif,
+} from 'lib/push/utils.js';
import {
type WebNotifInputData,
webNotifInputDataValidator,
@@ -31,8 +35,6 @@
wnsNotifInputDataValidator,
createWNSNotification,
} from 'lib/push/wns-notif-creators.js';
-import { oldValidUsernameRegex } from 'lib/shared/account-utils.js';
-import { isUserMentioned } from 'lib/shared/mention-utils.js';
import {
createMessageInfo,
shimUnsupportedRawMessageInfos,
@@ -245,36 +247,24 @@
const parentThreadInfo = threadInfo.parentThreadID
? threadInfos[threadInfo.parentThreadID]
: null;
- const updateBadge = threadInfo.currentUser.subscription.home;
- const displayBanner = threadInfo.currentUser.subscription.pushNotifs;
+
const username = userInfos[userID] && userInfos[userID].username;
- let resolvedUsername;
- if (getENSNames) {
- const userInfosWithENSNames = await getENSNames([userInfos[userID]]);
- resolvedUsername = userInfosWithENSNames[0].username;
- }
+ const { notifAllowed, badgeOnly } = await userAllowsNotif(
+ {
+ ...threadInfo.currentUser.subscription,
+ role: threadInfo.currentUser.role,
+ },
+ userID,
+ newMessageInfos,
+ userInfos,
+ username,
+ getENSNames,
+ );
- const userWasMentioned =
- username &&
- threadInfo.currentUser.role &&
- oldValidUsernameRegex.test(username) &&
- newMessageInfos.some(newMessageInfo => {
- const unwrappedMessageInfo =
- newMessageInfo.type === messageTypes.SIDEBAR_SOURCE
- ? newMessageInfo.sourceMessage
- : newMessageInfo;
- return (
- unwrappedMessageInfo.type === messageTypes.TEXT &&
- (isUserMentioned(username, unwrappedMessageInfo.text) ||
- (resolvedUsername &&
- isUserMentioned(resolvedUsername, unwrappedMessageInfo.text)))
- );
- });
- if (!updateBadge && !displayBanner && !userWasMentioned) {
+ if (!notifAllowed) {
return null;
}
- const badgeOnly = !displayBanner && !userWasMentioned;
const notifTargetUserInfo = { id: userID, username };
const notifTexts = await notifTextsForMessageInfo(
@@ -369,6 +359,7 @@
newRawMessageInfos: shimmedNewRawMessageInfos,
threadID: threadInfo.id,
collapseKey: notifInfo.collapseKey,
+ badgeOnly,
unreadCount,
platformDetails,
notifID: dbID,
diff --git a/lib/push/android-notif-creators.js b/lib/push/android-notif-creators.js
--- a/lib/push/android-notif-creators.js
+++ b/lib/push/android-notif-creators.js
@@ -38,6 +38,7 @@
+newRawMessageInfos: RawMessageInfo[],
+threadID: string,
+collapseKey: ?string,
+ +badgeOnly: boolean,
+unreadCount?: number,
+platformDetails: PlatformDetails,
}>;
@@ -49,6 +50,7 @@
newRawMessageInfos: t.list(rawMessageInfoValidator),
threadID: tID,
collapseKey: t.maybe(t.String),
+ badgeOnly: t.Boolean,
unreadCount: t.maybe(t.Number),
platformDetails: tPlatformDetails,
});
@@ -75,6 +77,7 @@
newRawMessageInfos,
threadID,
collapseKey,
+ badgeOnly,
unreadCount,
platformDetails,
notifID,
@@ -128,7 +131,7 @@
notification.data = {
...notification.data,
id,
- badgeOnly: '0',
+ badgeOnly: badgeOnly ? '1' : '0',
};
const messageInfos = JSON.stringify(newRawMessageInfos);
diff --git a/lib/push/apns-notif-creators.js b/lib/push/apns-notif-creators.js
--- a/lib/push/apns-notif-creators.js
+++ b/lib/push/apns-notif-creators.js
@@ -32,14 +32,12 @@
export type APNsNotifInputData = {
...CommonNativeNotifInputData,
- +badgeOnly: boolean,
+uniqueID: string,
};
export const apnsNotifInputDataValidator: TInterface<APNsNotifInputData> =
tShape<APNsNotifInputData>({
...commonNativeNotifInputDataValidator.meta.props,
- badgeOnly: t.Boolean,
uniqueID: t.String,
});
diff --git a/lib/push/send-utils.js b/lib/push/send-utils.js
--- a/lib/push/send-utils.js
+++ b/lib/push/send-utils.js
@@ -9,6 +9,7 @@
stringToVersionKey,
getDevicesByPlatform,
generateNotifUserInfoPromise,
+ userAllowsNotif,
} from './utils.js';
import { createWebNotification } from './web-notif-creators.js';
import { createWNSNotification } from './wns-notif-creators.js';
@@ -44,6 +45,7 @@
SenderDeviceDescriptor,
EncryptedNotifUtilsAPI,
} from '../types/notif-types.js';
+import type { ThreadSubscription } from '../types/subscription-types.js';
import type { RawThreadInfos } from '../types/thread-types.js';
import type { UserInfos } from '../types/user-types.js';
import { type GetENSNames } from '../utils/ens-helpers.js';
@@ -56,17 +58,27 @@
+cryptoID: string,
};
+export type ThreadSubscriptionWithRole = $ReadOnly<{
+ ...ThreadSubscription,
+ role: ?string,
+}>;
+
export type PushUserInfo = {
+devices: $ReadOnlyArray<Device>,
+messageInfos: RawMessageInfo[],
+messageDatas: MessageData[],
+ +subscriptions?: {
+ +[threadID: string]: ThreadSubscriptionWithRole,
+ },
};
export type PushInfo = { +[userID: string]: PushUserInfo };
type PushUserThreadInfo = {
+devices: $ReadOnlyArray<Device>,
- +threadIDs: Set<string>,
+ +threadsWithSubscriptions: {
+ [threadID: string]: ThreadSubscriptionWithRole,
+ },
};
function identityPlatformDetailsToPlatformDetails(
@@ -123,13 +135,15 @@
for (const memberInfo of threadInfo.members) {
if (
!isMemberActive(memberInfo) ||
- !hasPermission(memberInfo.permissions, 'visible')
+ !hasPermission(memberInfo.permissions, 'visible') ||
+ !memberInfo.subscription
) {
continue;
}
if (pushUserThreadInfos[memberInfo.id]) {
- pushUserThreadInfos[memberInfo.id].threadIDs.add(threadID);
+ pushUserThreadInfos[memberInfo.id].threadsWithSubscriptions[threadID] =
+ { ...memberInfo.subscription, role: memberInfo.role };
continue;
}
@@ -152,7 +166,9 @@
pushUserThreadInfos[memberInfo.id] = {
devices,
- threadIDs: new Set([threadID]),
+ threadsWithSubscriptions: {
+ [threadID]: { ...memberInfo.subscription, role: memberInfo.role },
+ },
};
}
}
@@ -163,28 +179,47 @@
for (const userID in pushUserThreadInfos) {
const pushUserThreadInfo = pushUserThreadInfos[userID];
- userPushInfoPromises[userID] = generateNotifUserInfoPromise(
- pushTypes.NOTIF,
- pushUserThreadInfo.devices,
- newMessageInfos,
- messageDatas,
- threadsToMessageIndices,
- pushUserThreadInfo.threadIDs,
- new Set(),
- (messageID: string) => (async () => messageInfos[messageID])(),
- userID,
- );
- userRescindInfoPromises[userID] = generateNotifUserInfoPromise(
- pushTypes.RESCIND,
- pushUserThreadInfo.devices,
- newMessageInfos,
- messageDatas,
- threadsToMessageIndices,
- pushUserThreadInfo.threadIDs,
- new Set(),
- (messageID: string) => (async () => messageInfos[messageID])(),
- userID,
- );
+ userPushInfoPromises[userID] = (async () => {
+ const pushInfosWithoutSubscriptions = await generateNotifUserInfoPromise(
+ pushTypes.NOTIF,
+ pushUserThreadInfo.devices,
+ newMessageInfos,
+ messageDatas,
+ threadsToMessageIndices,
+ Object.keys(pushUserThreadInfo.threadsWithSubscriptions),
+ new Set(),
+ (messageID: string) => (async () => messageInfos[messageID])(),
+ userID,
+ );
+ if (!pushInfosWithoutSubscriptions) {
+ return null;
+ }
+ return {
+ ...pushInfosWithoutSubscriptions,
+ subscriptions: pushUserThreadInfo.threadsWithSubscriptions,
+ };
+ })();
+
+ userRescindInfoPromises[userID] = (async () => {
+ const pushInfosWithoutSubscriptions = await generateNotifUserInfoPromise(
+ pushTypes.RESCIND,
+ pushUserThreadInfo.devices,
+ newMessageInfos,
+ messageDatas,
+ threadsToMessageIndices,
+ Object.keys(pushUserThreadInfo.threadsWithSubscriptions),
+ new Set(),
+ (messageID: string) => (async () => messageInfos[messageID])(),
+ userID,
+ );
+ if (!pushInfosWithoutSubscriptions) {
+ return null;
+ }
+ return {
+ ...pushInfosWithoutSubscriptions,
+ subscriptions: pushUserThreadInfo.threadsWithSubscriptions,
+ };
+ })();
}
const [pushInfo, rescindInfo] = await Promise.all([
@@ -202,13 +237,19 @@
rawMessageInfos: $ReadOnlyArray<RawMessageInfo>,
userID: string,
threadInfos: { +[id: string]: ThreadInfo },
+ subscriptions: ?{ +[threadID: string]: ThreadSubscriptionWithRole },
userInfos: UserInfos,
getENSNames: ?GetENSNames,
getFCNames: ?GetFCNames,
): Promise<?{
+notifTexts: ResolvedNotifTexts,
+newRawMessageInfos: $ReadOnlyArray<RawMessageInfo>,
+ +badgeOnly: boolean,
}> {
+ if (!subscriptions) {
+ return null;
+ }
+
const hydrateMessageInfo = (rawMessageInfo: RawMessageInfo) =>
createMessageInfo(rawMessageInfo, userID, userInfos, threadInfos);
@@ -233,9 +274,25 @@
? threadInfos[threadInfo.parentThreadID]
: null;
- // TODO: Using types from @Ashoat check ThreadSubscription and mentioning
+ const subscription = subscriptions[threadID];
+ if (!subscription) {
+ return null;
+ }
const username = userInfos[userID] && userInfos[userID].username;
+ const { notifAllowed, badgeOnly } = await userAllowsNotif(
+ subscription,
+ userID,
+ newMessageInfos,
+ userInfos,
+ username,
+ getENSNames,
+ );
+
+ if (!notifAllowed) {
+ return null;
+ }
+
const notifTargetUserInfo = { id: userID, username };
const notifTexts = await notifTextsForMessageInfo(
newMessageInfos,
@@ -249,7 +306,7 @@
return null;
}
- return { notifTexts, newRawMessageInfos };
+ return { notifTexts, newRawMessageInfos, badgeOnly };
}
async function buildNotifsForUserDevices(
@@ -258,6 +315,7 @@
rawMessageInfos: $ReadOnlyArray<RawMessageInfo>,
userID: string,
threadInfos: { +[id: string]: ThreadInfo },
+ subscriptions: ?{ +[threadID: string]: ThreadSubscriptionWithRole },
userInfos: UserInfos,
getENSNames: ?GetENSNames,
getFCNames: ?GetFCNames,
@@ -270,6 +328,7 @@
rawMessageInfos,
userID,
threadInfos,
+ subscriptions,
userInfos,
getENSNames,
getFCNames,
@@ -279,7 +338,8 @@
return null;
}
- const { notifTexts, newRawMessageInfos } = notifTextWithNewRawMessageInfos;
+ const { notifTexts, newRawMessageInfos, badgeOnly } =
+ notifTextWithNewRawMessageInfos;
const [{ threadID }] = newRawMessageInfos;
const promises: Array<
@@ -311,7 +371,7 @@
newRawMessageInfos: shimmedNewRawMessageInfos,
threadID,
collapseKey: undefined,
- badgeOnly: false,
+ badgeOnly,
unreadCount: undefined,
platformDetails,
uniqueID: uuidv4(),
@@ -352,6 +412,7 @@
newRawMessageInfos: shimmedNewRawMessageInfos,
threadID,
collapseKey: undefined,
+ badgeOnly,
unreadCount: undefined,
platformDetails,
notifID: uuidv4(),
@@ -394,7 +455,7 @@
newRawMessageInfos: shimmedNewRawMessageInfos,
threadID,
collapseKey: undefined,
- badgeOnly: false,
+ badgeOnly,
unreadCount: undefined,
platformDetails,
uniqueID: uuidv4(),
@@ -534,6 +595,7 @@
[rawMessageInfos],
userID,
threadInfos,
+ pushInfo[userID].subscriptions,
userInfos,
getENSNames,
getFCNames,
diff --git a/lib/push/utils.js b/lib/push/utils.js
--- a/lib/push/utils.js
+++ b/lib/push/utils.js
@@ -1,15 +1,21 @@
// @flow
import invariant from 'invariant';
-import type { Device } from './send-utils.js';
+import type { Device, ThreadSubscriptionWithRole } from './send-utils.js';
+import { oldValidUsernameRegex } from '../shared/account-utils.js';
+import { isUserMentioned } from '../shared/mention-utils.js';
import { type PushType } from '../shared/messages/message-spec.js';
import { messageSpecs } from '../shared/messages/message-specs.js';
import type { Platform } from '../types/device-types.js';
-import {
- type MessageData,
- type RawMessageInfo,
+import { messageTypes } from '../types/message-types-enum.js';
+import type {
+ MessageData,
+ RawMessageInfo,
+ MessageInfo,
} from '../types/message-types.js';
import type { NotificationTargetDevice } from '../types/notif-types.js';
+import type { GlobalUserInfo, UserInfo } from '../types/user-types.js';
+import type { GetENSNames } from '../utils/ens-helpers.js';
export type VersionKey = {
+codeVersion: number,
@@ -88,7 +94,7 @@
newMessageInfos: $ReadOnlyArray<RawMessageInfo>,
messageDatas: $ReadOnlyArray<MessageData>,
threadsToMessageIndices: $ReadOnlyMap<string, number[]>,
- threadIDs: $ReadOnlySet<string>,
+ threadIDs: $ReadOnlyArray<string>,
userNotMemberOfSubthreads: Set<string>,
fetchMessageInfoByID: (messageID: string) => Promise<any>,
userID: string,
@@ -158,9 +164,53 @@
};
}
+async function userAllowsNotif(
+ subscription: ThreadSubscriptionWithRole,
+ userID: string,
+ newMessageInfos: $ReadOnlyArray<MessageInfo>,
+ userInfos: { +[string]: UserInfo | GlobalUserInfo },
+ username: ?string,
+ getENSNames: ?GetENSNames,
+): Promise<{
+ +notifAllowed: boolean,
+ +badgeOnly: boolean,
+}> {
+ const updateBadge = subscription.home;
+ const displayBanner = subscription.pushNotifs;
+
+ let resolvedUsername;
+ if (getENSNames) {
+ const userInfosWithENSNames = await getENSNames([userInfos[userID]]);
+ resolvedUsername = userInfosWithENSNames[0].username;
+ }
+
+ const userWasMentioned =
+ username &&
+ subscription.role &&
+ oldValidUsernameRegex.test(username) &&
+ newMessageInfos.some(newMessageInfo => {
+ const unwrappedMessageInfo =
+ newMessageInfo.type === messageTypes.SIDEBAR_SOURCE
+ ? newMessageInfo.sourceMessage
+ : newMessageInfo;
+ return (
+ unwrappedMessageInfo.type === messageTypes.TEXT &&
+ (isUserMentioned(username, unwrappedMessageInfo.text) ||
+ (resolvedUsername &&
+ isUserMentioned(resolvedUsername, unwrappedMessageInfo.text)))
+ );
+ });
+
+ const notifAllowed = !!updateBadge || !!displayBanner || !!userWasMentioned;
+ const badgeOnly = !displayBanner && !userWasMentioned;
+
+ return { notifAllowed, badgeOnly };
+}
+
export {
stringToVersionKey,
versionKeyToString,
getDevicesByPlatform,
generateNotifUserInfoPromise,
+ userAllowsNotif,
};
diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js
--- a/lib/shared/thread-utils.js
+++ b/lib/shared/thread-utils.js
@@ -45,6 +45,7 @@
MemberInfoWithPermissions,
RoleInfo,
ThreadInfo,
+ MinimallyEncodedThickMemberInfo,
} from '../types/minimally-encoded-thread-permissions-types.js';
import {
decodeMinimallyEncodedRoleInfo,
@@ -223,7 +224,9 @@
);
}
-function isMemberActive(memberInfo: MemberInfoWithPermissions): boolean {
+function isMemberActive(
+ memberInfo: MemberInfoWithPermissions | MinimallyEncodedThickMemberInfo,
+): boolean {
const role = memberInfo.role;
return role !== null && role !== undefined;
}
diff --git a/lib/types/notif-types.js b/lib/types/notif-types.js
--- a/lib/types/notif-types.js
+++ b/lib/types/notif-types.js
@@ -92,7 +92,7 @@
+prefix?: string,
+threadID: string,
+collapseID?: string,
- +badgeOnly?: '0',
+ +badgeOnly?: '0' | '1',
+encryptionFailed?: '1',
}>;

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 27, 1:33 AM (22 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2587251
Default Alt Text
D12539.id41716.diff (16 KB)

Event Timeline