Notifications and sending songs to friends
Reactions to your songs, new followers, and songs sent to you are now notifications: a bell on the feed (app and website) with an unread count that updates live, and a list that marks them read. "Send ✉" on a song sends it to people who follow you, with an optional note. Settings picks which kinds to be notified about. Push delivery uses no third-party accounts: - Android: UnifiedPush through a distributor app (ntfy), pointed at our own ntfy server (docker-compose.ntfy.yml). Works the same in the F-Droid build; no Firebase. - Browsers: standard Web Push from the existing service worker. Both use Web Push encryption with a VAPID key pair the server makes and keeps in the database. Push addresses are checked like any other user-supplied URL. Setup is in docs/PUSH.md; the privacy page covers the new data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,10 +52,28 @@ export const updateMeSchema = z.object({
|
||||
.transform((s) => [...new Set(s)])
|
||||
.nullable()
|
||||
.optional(),
|
||||
notifyPrefs: z
|
||||
.object({ reaction: z.boolean(), follow: z.boolean(), share: z.boolean() })
|
||||
.partial()
|
||||
.optional(),
|
||||
/** Mark onboarding as finished. */
|
||||
onboarded: z.literal(true).optional(),
|
||||
});
|
||||
|
||||
/** Send a song to people who follow you. */
|
||||
export const sendSongSchema = z.object({
|
||||
trackId: z.uuid(),
|
||||
to: z.array(z.string().min(1).max(32)).min(1).max(20),
|
||||
message: z.string().trim().max(280).nullable().optional(),
|
||||
});
|
||||
|
||||
/** A browser's or phone's push subscription (both use Web Push encryption keys). */
|
||||
export const pushSubscriptionSchema = z.object({
|
||||
kind: z.enum(['web', 'unifiedpush']),
|
||||
endpoint: z.url({ protocol: /^https?$/ }).max(2000),
|
||||
keys: z.object({ p256dh: z.string().min(20).max(200), auth: z.string().min(8).max(100) }),
|
||||
});
|
||||
|
||||
export const setFeaturedSchema = z.union([
|
||||
z.object({ deezerId: z.string().regex(/^\d+$/), comment: z.string().trim().max(280).nullable().optional() }),
|
||||
z.object({ trackId: z.uuid(), comment: z.string().trim().max(280).nullable().optional() }),
|
||||
@@ -72,6 +90,8 @@ export type ChangePasswordInput = z.infer<typeof changePasswordSchema>;
|
||||
export type ChangeEmailInput = z.infer<typeof changeEmailSchema>;
|
||||
export type UpdateMeInput = z.infer<typeof updateMeSchema>;
|
||||
export type SetFeaturedInput = z.infer<typeof setFeaturedSchema>;
|
||||
export type SendSongInput = z.infer<typeof sendSongSchema>;
|
||||
export type PushSubscriptionInput = z.infer<typeof pushSubscriptionSchema>;
|
||||
|
||||
export const jellyfinConnectSchema = z.object({
|
||||
serverUrl: z.string().trim().min(1).max(500),
|
||||
|
||||
Reference in New Issue
Block a user