Add in-app + real-time notifications (SignalR/mock, Iran-friendly)
- AppNotification + OnlineService.onNotification (hub event + mock periodic) — no FCM/APNs (blocked in Iran); uses the existing realtime channel - notification-store + pushNotification(); 🔔 bell with unread badge in TopBar, notifications screen, global toaster (plays notify sfx) - Wired events: daily reward, post-match achievements, friend requests - Closed-app push (Pushe/Najva/Chabok) noted as a later step (needs provider keys) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { create } from "zustand";
|
||||
import { CreateRoomOptions, MatchmakingOptions, getService } from "./online/service";
|
||||
import { pushNotification } from "./notification-store";
|
||||
import {
|
||||
ChatMessage,
|
||||
Friend,
|
||||
@@ -49,6 +50,7 @@ let roomUnsub: (() => void) | null = null;
|
||||
let mmUnsub: (() => void) | null = null;
|
||||
let friendUnsub: (() => void) | null = null;
|
||||
let chatUnsub: (() => void) | null = null;
|
||||
const seenRequests = new Set<string>();
|
||||
|
||||
export const useOnlineStore = create<OnlineStore>((set, get) => ({
|
||||
friends: [],
|
||||
@@ -61,6 +63,18 @@ export const useOnlineStore = create<OnlineStore>((set, get) => ({
|
||||
const svc = getService();
|
||||
const [friends, requests] = await Promise.all([svc.listFriends(), svc.listRequests()]);
|
||||
set({ friends, requests });
|
||||
for (const r of requests) {
|
||||
if (seenRequests.has(r.id)) continue;
|
||||
seenRequests.add(r.id);
|
||||
pushNotification({
|
||||
kind: "friend_request",
|
||||
titleFa: "درخواست دوستی جدید",
|
||||
titleEn: "New friend request",
|
||||
bodyFa: r.from.displayName,
|
||||
bodyEn: r.from.displayName,
|
||||
icon: "👥",
|
||||
});
|
||||
}
|
||||
if (!friendUnsub) friendUnsub = svc.onFriends((f) => set({ friends: f }));
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user