v0.12.40 iso notificastion bug fix
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rosterchirp-backend",
|
||||
"version": "0.12.39",
|
||||
"version": "0.12.40",
|
||||
"description": "RosterChirp backend server",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
|
||||
2
build.sh
2
build.sh
@@ -13,7 +13,7 @@
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
set -euo pipefail
|
||||
|
||||
VERSION="${1:-0.12.39}"
|
||||
VERSION="${1:-0.12.40}"
|
||||
ACTION="${2:-}"
|
||||
REGISTRY="${REGISTRY:-}"
|
||||
IMAGE_NAME="rosterchirp"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rosterchirp-frontend",
|
||||
"version": "0.12.39",
|
||||
"version": "0.12.40",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -13,9 +13,13 @@ const FIREBASE_CONFIG = {
|
||||
appId: "1:126479377334:web:280abdd135cf7e0c50d717"
|
||||
};
|
||||
|
||||
// Initialise Firebase synchronously so the push listener is ready immediately
|
||||
// Initialise Firebase synchronously so the push listener is ready immediately.
|
||||
// Skip on iOS — iOS PWAs use standard W3C WebPush (VAPID), not FCM. Initialising
|
||||
// firebase.messaging() on iOS registers a second internal push listener alongside
|
||||
// the custom one below, causing every notification to appear twice.
|
||||
const isIOS = /iPhone|iPad|iPod/.test(self.navigator?.userAgent || '');
|
||||
let messaging = null;
|
||||
if (FIREBASE_CONFIG.apiKey !== '__FIREBASE_API_KEY__') {
|
||||
if (!isIOS && FIREBASE_CONFIG.apiKey !== '__FIREBASE_API_KEY__') {
|
||||
firebase.initializeApp(FIREBASE_CONFIG);
|
||||
messaging = firebase.messaging();
|
||||
console.log('[SW] Firebase initialised');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useSocket } from '../contexts/SocketContext.jsx';
|
||||
import { useAuth } from '../contexts/AuthContext.jsx';
|
||||
import { useToast } from '../contexts/ToastContext.jsx';
|
||||
@@ -35,6 +35,9 @@ export default function Chat() {
|
||||
const toast = useToast();
|
||||
|
||||
const [groups, setGroups] = useState({ publicGroups: [], privateGroups: [] });
|
||||
// Ref so visibility/reconnect handlers always see the latest groups without
|
||||
// being dependencies of the socket effect (which would cause excessive re-runs)
|
||||
const groupsRef = useRef({ publicGroups: [], privateGroups: [] });
|
||||
const [onlineUserIds, setOnlineUserIds] = useState(new Set());
|
||||
const [activeGroupId, setActiveGroupId] = useState(null);
|
||||
const [chatHasText, setChatHasText] = useState(false);
|
||||
@@ -74,6 +77,9 @@ export default function Chat() {
|
||||
|
||||
useEffect(() => { loadGroups(); }, [loadGroups]);
|
||||
|
||||
// Keep groupsRef in sync so visibility/reconnect handlers can read current groups
|
||||
useEffect(() => { groupsRef.current = groups; }, [groups]);
|
||||
|
||||
// Load feature flags + current user's group memberships on mount
|
||||
const loadFeatures = useCallback(() => {
|
||||
api.getSettings().then(({ settings }) => {
|
||||
@@ -424,14 +430,40 @@ export default function Chat() {
|
||||
socket.on('group:updated', handleGroupUpdated);
|
||||
socket.on('session:displaced', handleSessionDisplaced);
|
||||
|
||||
// Bug B fix: on reconnect, reload groups to catch any messages missed while offline
|
||||
const handleReconnect = () => { loadGroups(); };
|
||||
// On reconnect or visibility restore: reload groups AND badge any groups that
|
||||
// received messages while the iOS PWA was backgrounded (socket was dead, so
|
||||
// message:new events were never received — only push notifications arrived).
|
||||
const checkForMissedMessages = () => {
|
||||
api.getGroups().then(newGroups => {
|
||||
const prev = groupsRef.current;
|
||||
setGroups(newGroups);
|
||||
const allPrev = [...prev.publicGroups, ...prev.privateGroups];
|
||||
const allNew = [...newGroups.publicGroups, ...newGroups.privateGroups];
|
||||
setUnreadGroups(prevUnread => {
|
||||
const next = new Map(prevUnread);
|
||||
for (const ng of allNew) {
|
||||
if (ng.id === activeGroupId) continue; // currently open — no badge
|
||||
if (ng.last_message_user_id === user?.id) continue; // own message
|
||||
const pg = allPrev.find(g => g.id === ng.id);
|
||||
const isNewer = ng.last_message_at && (
|
||||
!pg?.last_message_at ||
|
||||
new Date(ng.last_message_at) > new Date(pg.last_message_at)
|
||||
);
|
||||
if (isNewer && !next.has(ng.id)) {
|
||||
next.set(ng.id, 1);
|
||||
}
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
const handleReconnect = () => { checkForMissedMessages(); };
|
||||
socket.on('connect', handleReconnect);
|
||||
|
||||
// Bug B fix: also reload on visibility restore if socket is already connected
|
||||
const handleVisibility = () => {
|
||||
if (document.visibilityState === 'visible' && socket.connected) {
|
||||
loadGroups();
|
||||
checkForMissedMessages();
|
||||
}
|
||||
};
|
||||
document.addEventListener('visibilitychange', handleVisibility);
|
||||
|
||||
Reference in New Issue
Block a user