Skip to content

Commit c18709d

Browse files
Dean SoferDean Sofer
authored andcommitted
Cursor assisted notifications WIP
1 parent 0a03bc7 commit c18709d

File tree

4 files changed

+66
-56
lines changed

4 files changed

+66
-56
lines changed

public/firebase-messaging-sw.js

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
// TODO: Identify how to create service worker with VITE properly
21
// --- IMPORTANT: Service Worker for Background Messages ---
3-
// Create a `firebase-messaging-sw.js` file in your public directory.
42
// This file handles messages when your web app is not in the foreground.
53
// It needs to import and initialize Firebase Messaging itself, using compat!
64

75
// public/firebase-messaging-sw.js (using compat)
86
importScripts('https://www.gstatic.com/firebasejs/10.12.4/firebase-app-compat.js');
97
importScripts('https://www.gstatic.com/firebasejs/10.12.4/firebase-messaging-compat.js');
108

11-
// Your Firebase configuration
9+
// Your Firebase configuration @see src/firebase.config.ts
1210
const firebaseConfig = {
1311
apiKey: "AIzaSyDSTc5VVNNT32jRE4m8qr7hVbI8ahaIsRc",
1412
authDomain: "peaceinthemiddleeast.firebaseapp.com",
@@ -20,21 +18,68 @@ const firebaseConfig = {
2018
measurementId: "G-NKGPNTLDF1"
2119
};
2220

23-
// Initialize Firebase using the compat API
24-
const firebaseApp = firebase.initializeApp(firebaseConfig); // Use firebase.initializeApp
21+
firebase.initializeApp(firebaseConfig);
2522

26-
// Retrieve firebase messaging instance using the compat API
27-
const messaging = firebaseApp.messaging(); // Use firebaseApp.messaging()
23+
let currentUserId = null;
24+
let processedMoveIds = new Set();
2825

29-
// Handle incoming messages in the background (using compat messaging)
30-
messaging.onBackgroundMessage((payload) => { // Use messaging.onBackgroundMessage
26+
console.log('Service Worker: Loaded and Firebase initialized.');
27+
28+
firebase.messaging().onBackgroundMessage((payload) => {
3129
console.log('Received background message ', payload);
3230

3331
const notificationTitle = payload.notification.title;
3432
const notificationOptions = {
3533
body: payload.notification.body,
36-
icon: '/android-chrome-512x512.png' // Or your app icon
34+
icon: '/android-chrome-512x512.png'
3735
};
3836

3937
self.registration.showNotification(notificationTitle, notificationOptions);
4038
});
39+
40+
self.addEventListener('notificationclick', event => {
41+
console.log('Service Worker: Notification clicked.', event.notification);
42+
event.notification.close();
43+
44+
const friend = event.notification.data.friend; // This is opponent's UID, used for URL path
45+
// const gameId = event.notification.data.gameId; // Game's unique key, if needed for other logic
46+
// const moveId = event.notification.data.moveId; // Move was removed when notification was shown
47+
48+
if (friend) {
49+
// App URL structure is /:friend (e.g., /user123)
50+
const targetUrl = `${self.location.origin}/${friend}`;
51+
event.waitUntil(
52+
clients.matchAll({ type: 'window', includeUncontrolled: true }).then(windowClients => {
53+
for (let i = 0; i < windowClients.length; i++) {
54+
const client = windowClients[i];
55+
// Check if a window/tab with this game (friend) is already open.
56+
if ((client.url === targetUrl || client.url === `${targetUrl}/`) && 'focus' in client) {
57+
console.log('Service Worker: Focusing existing window for friend:', friend);
58+
return client.focus();
59+
}
60+
}
61+
if (clients.openWindow) {
62+
console.log('Service Worker: Opening new window for friend:', friend);
63+
return clients.openWindow(targetUrl);
64+
}
65+
})
66+
);
67+
} else {
68+
console.log('Service Worker: No friend in notification data, opening main page.');
69+
if (clients.openWindow) { // Fallback to open the main page
70+
return clients.openWindow('/');
71+
}
72+
}
73+
});
74+
75+
self.addEventListener('activate', event => {
76+
console.log('Service Worker: Activating...');
77+
event.waitUntil(
78+
self.clients.claim().then(() => { // Take control of all clients immediately
79+
console.log('Service Worker: Claimed clients.');
80+
// On activation, client should send 'SET_USER_ID' if user is logged in.
81+
// If SW persisted userId (e.g. in IndexedDB), it could be read here to setup listener early.
82+
// Example: restoreUserIdAndSetupListener();
83+
})
84+
);
85+
});

src/firebase-messaging-setup.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,11 @@
1-
// client/src/firebase-messaging-setup.ts (using compat)
2-
3-
// Import the compat versions of the SDKs you need
4-
import firebase from 'firebase/compat/app';
5-
import 'firebase/compat/messaging';
6-
import 'firebase/compat/database';
7-
import 'firebase/compat/auth';
8-
9-
// Your Firebase configuration (get this from your Firebase project settings)
10-
const firebaseConfig = {
11-
apiKey: "AIzaSyDSTc5VVNNT32jRE4m8qr7hVbI8ahaIsRc",
12-
authDomain: "peaceinthemiddleeast.firebaseapp.com",
13-
databaseURL: "https://peaceinthemiddleeast-default-rtdb.firebaseio.com",
14-
projectId: "peaceinthemiddleeast",
15-
storageBucket: "peaceinthemiddleeast.appspot.com",
16-
messagingSenderId: "529824094542",
17-
appId: "1:529824094542:web:eadc5cf0dc140a2b0de61f",
18-
measurementId: "G-NKGPNTLDF1"
19-
};
1+
import firebase from './firebase.config';
202

213
// Initialize Firebase (using the compat app import)
22-
const firebaseApp = firebase.initializeApp(firebaseConfig);
4+
// const firebase = firebase.initializeApp(firebaseConfig);
235
// Access services directly from the app instance or the global firebase object
24-
const messaging = firebaseApp.messaging(); // Or firebase.messaging() if using script tags
25-
const db = firebaseApp.database(); // Or firebase.database()
26-
const auth = firebaseApp.auth(); // Or firebase.auth()
6+
const messaging = firebase.messaging(); // Or firebase.messaging() if using script tags
7+
const db = firebase.database(); // Or firebase.database()
8+
const auth = firebase.auth(); // Or firebase.auth()
279

2810

2911
// Get the FCM registration token and save it to the database

src/firebaseConfig.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/index.tsx

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { StrictMode, useEffect, useState, useCallback, type DragEventHandler } from "react";
22
import ReactDOM from 'react-dom/client'
3-
import firebase from 'firebase/compat/app';
4-
import 'firebase/compat/database';
53
// TODO: Upgrade to modular after firebaseui upgrades
64
// import { initializeApp } from 'firebase/app';
75
import type { Match, Move, GameType, SnapshotOrNullType, UserData, ModalState } from "./Types";
@@ -17,23 +15,9 @@ import './index.css'
1715
import './Board/Board.css';
1816
import './Toolbar.css'
1917
import { calculate, newGame, rollDie, vibrate } from './Utils';
20-
import { registerSW } from 'virtual:pwa-register';
18+
import firebase from "./firebase.config";
2119
import { saveMessagingDeviceToken } from './firebase-messaging-setup';
2220

23-
24-
25-
// Start Firebase
26-
firebase.initializeApp({
27-
apiKey: "AIzaSyDSTc5VVNNT32jRE4m8qr7hVbI8ahaIsRc",
28-
authDomain: "peaceinthemiddleeast.firebaseapp.com",
29-
databaseURL: "https://peaceinthemiddleeast-default-rtdb.firebaseio.com",
30-
projectId: "peaceinthemiddleeast",
31-
storageBucket: "peaceinthemiddleeast.appspot.com",
32-
messagingSenderId: "529824094542",
33-
appId: "1:529824094542:web:eadc5cf0dc140a2b0de61f",
34-
measurementId: "G-NKGPNTLDF1"
35-
});
36-
3721
// Start React
3822
ReactDOM.createRoot(document.getElementById('root')!).render(<StrictMode><App /></StrictMode>)
3923

@@ -122,7 +106,7 @@ export function App() {
122106
console.log('Resetting', match?.game);
123107
let data = newGame()
124108
if (match?.game)
125-
firebase.database().ref(`games/${match?.game}`).set(data);
109+
database.ref(`games/${match?.game}`).set(data);
126110
setGame(data);
127111
toggle(false)
128112
}
@@ -138,7 +122,7 @@ export function App() {
138122
// onLogin/Logout
139123
const unregisterAuthObserver = firebase.auth().onAuthStateChanged(async authUser => {
140124
if (authUser) {
141-
const userRef = firebase.database().ref(`users/${authUser.uid}`)
125+
const userRef = database.ref(`users/${authUser.uid}`)
142126
let snapshot = await userRef.get()
143127
if (!snapshot.exists()) {
144128
// Upload initial user data
@@ -185,8 +169,8 @@ export function App() {
185169
// Subscribe to match
186170
useEffect(() => {
187171
if (match?.game) {
188-
const gameRef = firebase.database().ref(`games/${match?.game}`)
189-
const onValue = (snapshot: firebase.database.DataSnapshot) => {
172+
const gameRef = database.ref(`games/${match?.game}`)
173+
const onValue = (snapshot: DataSnapshot) => {
190174
const value = snapshot.val();
191175
if (value) {
192176
setGame(game => {
@@ -217,7 +201,7 @@ export function App() {
217201
if (game.turn === user?.val().uid)
218202
return console.log("You cannot roll the dice twice in a row.");
219203

220-
firebase.database().ref(`games/${match?.game}`).update({
204+
database.ref(`games/${match?.game}`).update({
221205
dice,
222206
color: game.color === 'white' ? 'black' : 'white',
223207
turn: user?.val().uid,

0 commit comments

Comments
 (0)