Skip to content

Commit 61f0278

Browse files
authored
Merge pull request #10 from nyoung697/main
Add additional notification fields
2 parents cc9a70b + b334c66 commit 61f0278

File tree

2 files changed

+144
-16
lines changed

2 files changed

+144
-16
lines changed

src/component/internal.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { internalAction, internalMutation } from "./functions.js";
33
import { internal } from "./_generated/api.js";
44
import { Id } from "./_generated/dataModel.js";
55
import { ensureCoordinator } from "./helpers.js";
6+
import { notificationFields } from "./schema.js";
67

78
export const markNotificationState = internalMutation({
89
args: {
@@ -145,12 +146,20 @@ export const coordinateSendingPushNotifications = internalMutation({
145146
return {
146147
message: {
147148
to: n.token,
149+
_contentAvailable: n.metadata._contentAvailable ?? undefined,
150+
data: n.metadata.data ?? undefined,
148151
title: n.metadata.title,
149-
subtitle: n.metadata.subtitle ?? undefined,
150152
body: n.metadata.body ?? undefined,
151-
sound: n.metadata.sound ?? "default",
152-
data: n.metadata.data ?? undefined,
153-
categoryIdentifier: n.metadata.categoryIdentifier ?? undefined,
153+
ttl: n.metadata.ttl ?? undefined,
154+
expiration: n.metadata.expiration ?? undefined,
155+
priority: n.metadata.priority ?? undefined,
156+
subtitle: n.metadata.subtitle ?? undefined,
157+
sound: n.metadata.sound ?? undefined,
158+
badge: n.metadata.badge ?? undefined,
159+
interruptionLevel: n.metadata.interruptionLevel ?? undefined,
160+
channelId: n.metadata.channelId ?? undefined,
161+
categoryId: n.metadata.categoryId ?? undefined,
162+
mutableContent: n.metadata.mutableContent ?? undefined,
154163
},
155164
_id: n._id,
156165
};
@@ -195,12 +204,7 @@ export const action_sendPushNotifications = internalAction({
195204
v.object({
196205
message: v.object({
197206
to: v.string(),
198-
title: v.string(),
199-
subtitle: v.optional(v.string()),
200-
body: v.optional(v.string()),
201-
sound: v.string(),
202-
data: v.optional(v.any()),
203-
categoryIdentifier: v.optional(v.string()),
207+
...notificationFields
204208
}),
205209
_id: v.id("notifications"),
206210
})

src/component/schema.ts

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,140 @@
11
import { defineSchema, defineTable } from "convex/server";
2-
import { ObjectType, v } from "convex/values";
2+
import { v } from "convex/values";
33

4+
// https://docs.expo.dev/push-notifications/sending-notifications/#message-request-format
45
export const notificationFields = {
6+
_contentAvailable: v.optional(v.boolean()),
7+
data: v.optional(v.any()),
58
title: v.string(),
6-
subtitle: v.optional(v.string()),
79
body: v.optional(v.string()),
8-
sound: v.optional(v.string()),
9-
data: v.optional(v.any()),
10-
categoryIdentifier: v.optional(v.string()),
10+
ttl: v.optional(v.number()),
11+
expiration: v.optional(v.number()),
12+
priority: v.optional(v.union(v.literal("default"), v.literal("normal"), v.literal("high"))),
13+
subtitle: v.optional(v.string()),
14+
sound: v.optional(v.union(v.string(), v.null())),
15+
badge: v.optional(v.number()),
16+
interruptionLevel: v.optional(v.union(v.literal("active"), v.literal("critical"), v.literal("passive"), v.literal("time-sensitive"))),
17+
channelId: v.optional(v.string()),
18+
categoryId: v.optional(v.string()),
19+
mutableContent: v.optional(v.boolean()),
1120
};
1221

13-
export type NotificationFields = ObjectType<typeof notificationFields>;
22+
/**
23+
* Notification fields for push notifications.
24+
*/
25+
export type NotificationFields = {
26+
/**
27+
* iOS Only
28+
*
29+
* When this is set to true, the notification will cause the iOS app to start in the background to run a background task.
30+
* Your app needs to be configured to support this.
31+
*/
32+
_contentAvailable?: boolean;
33+
34+
/**
35+
* Android and iOS
36+
*
37+
* A JSON object delivered to your app. It may be up to about 4KiB;
38+
* the total notification payload sent to Apple and Google must be at most 4KiB or else you will get a "Message Too Big" error.
39+
*/
40+
data?: any
41+
42+
/**
43+
* Android and iOS
44+
*
45+
* The title to display in the notification. Often displayed above the notification body.
46+
* Maps to AndroidNotification.title and aps.alert.title.
47+
*/
48+
title: string;
49+
50+
/**
51+
* Android and iOS
52+
*
53+
* The message to display in the notification. Maps to AndroidNotification.body and aps.alert.body.
54+
*/
55+
body?: string;
56+
57+
/**
58+
* Android and iOS
59+
*
60+
* Time to Live: the number of seconds for which the message may be kept around for redelivery
61+
* if it hasn't been delivered yet. Defaults to undefined to use the respective defaults of each provider
62+
* (1 month for Android/FCM as well as iOS/APNs).
63+
*/
64+
ttl?: number;
65+
66+
/**
67+
* Android and iOS
68+
*
69+
* Timestamp since the Unix epoch specifying when the message expires.
70+
* Same effect as ttl (ttl takes precedence over expiration).
71+
*/
72+
expiration?: number;
73+
74+
/**
75+
* Android and iOS
76+
*
77+
* The delivery priority of the message.
78+
* Specify default or omit this field to use the default priority on each platform ("normal" on Android and "high" on iOS).
79+
*/
80+
priority?: 'default' | 'normal' | 'high';
81+
82+
/**
83+
* iOS Only
84+
*
85+
* The subtitle to display in the notification below the title.
86+
* Maps to aps.alert.subtitle.
87+
*/
88+
subtitle?: string;
89+
90+
/**
91+
* iOS Only
92+
*
93+
* Play a sound when the recipient receives this notification. Specify default to play the device's default notification sound,
94+
* or omit this field to play no sound. Custom sounds need to be configured via the config plugin and
95+
* then specified including the file extension. Example: bells_sound.wav.
96+
*/
97+
sound?: string | null;
98+
99+
/**
100+
* iOS Only
101+
*
102+
* Number to display in the badge on the app icon. Specify zero to clear the badge.
103+
*/
104+
badge?: number;
105+
106+
/**
107+
* iOS Only
108+
*
109+
* The importance and delivery timing of a notification.
110+
* The string values correspond to the UNNotificationInterruptionLevel enumeration cases.
111+
*/
112+
interruptionLevel?: 'active' | 'critical' | 'passive' | 'time-sensitive';
113+
114+
/**
115+
* Android Only
116+
*
117+
* ID of the Notification Channel through which to display this notification.
118+
* If an ID is specified but the corresponding channel does not exist on the device (that has not yet been created by your app),
119+
* the notification will not be displayed to the user.
120+
*/
121+
channelId?: string;
122+
123+
/**
124+
* Android and iOS
125+
*
126+
* ID of the notification category that this notification is associated with.
127+
*/
128+
categoryId?: string;
129+
130+
/**
131+
* iOS Only
132+
*
133+
* Specifies whether this notification can be intercepted by the client app.
134+
* Defaults to false.
135+
*/
136+
mutableContent?: boolean;
137+
};
14138

15139
export const notificationState = v.union(
16140
v.literal("awaiting_delivery"),

0 commit comments

Comments
 (0)