Nachrichten: kein Pushover wenn Empfänger aktiv im Chat
This commit is contained in:
@@ -254,6 +254,8 @@ if (!userCols2.includes('last_active_at'))
|
||||
db.exec("ALTER TABLE users ADD COLUMN last_active_at DATETIME DEFAULT NULL");
|
||||
if (!userCols2.includes('hidden'))
|
||||
db.exec("ALTER TABLE users ADD COLUMN hidden INTEGER NOT NULL DEFAULT 0");
|
||||
if (!userCols2.includes('chat_active_at'))
|
||||
db.exec("ALTER TABLE users ADD COLUMN chat_active_at DATETIME DEFAULT NULL");
|
||||
|
||||
// ── Login-Sicherheit ──────────────────────────────────────────────────────────
|
||||
// Spalten für Account-Lockout in users-Tabelle
|
||||
|
||||
@@ -38,6 +38,17 @@ router.post('/keys', authenticate, (req, res) => {
|
||||
});
|
||||
|
||||
// ── Users ─────────────────────────────────────────────────────────────────────
|
||||
// Presence: User ist gerade aktiv im Chat
|
||||
router.post('/presence', authenticate, (req, res) => {
|
||||
const { active } = req.body;
|
||||
if (active) {
|
||||
db.prepare("UPDATE users SET chat_active_at=datetime('now','localtime') WHERE id=?").run(req.user.id);
|
||||
} else {
|
||||
db.prepare("UPDATE users SET chat_active_at=NULL WHERE id=?").run(req.user.id);
|
||||
}
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
router.get('/users', authenticate, (req, res) => {
|
||||
const me = req.user.id;
|
||||
const isAdmin = req.user.role === 'admin';
|
||||
@@ -120,9 +131,15 @@ router.post('/messages/:userId', authenticate, async (req, res) => {
|
||||
const senderName = db.prepare('SELECT username FROM users WHERE id = ?').get(me)?.username || 'Jemand';
|
||||
const pushover = db.prepare('SELECT * FROM pushover_settings WHERE user_id = ?').get(recipId);
|
||||
if (pushover) {
|
||||
// Kein Push wenn Empfänger gerade im Chat ist (aktiv in letzten 45 Sekunden)
|
||||
const presence = db.prepare(`
|
||||
SELECT chat_active_at FROM users WHERE id=? AND chat_active_at > datetime('now','localtime','-45 seconds')
|
||||
`).get(recipId);
|
||||
if (!presence) {
|
||||
await sendPushover(pushover.user_key, pushover.app_token, 'DickenDock', `Neue Nachricht von ${senderName}`,
|
||||
{ retry: pushover.retry, expire: pushover.expire });
|
||||
}
|
||||
}
|
||||
|
||||
res.json({ id: result.lastInsertRowid });
|
||||
});
|
||||
|
||||
@@ -95,6 +95,40 @@ export default function Nachrichten({ toast, mobile }) {
|
||||
const bottomRef = useRef(null);
|
||||
const pollRef = useRef(null);
|
||||
const pickerRef = useRef(null);
|
||||
const heartbeatRef = useRef(null);
|
||||
|
||||
// Presence Heartbeat: solange Nachrichten offen + Tab sichtbar → aktiv
|
||||
useEffect(() => {
|
||||
const sendPresence = (active) => api('/tools/nachrichten/presence', { method:'POST', body:{ active } }).catch(()=>{});
|
||||
|
||||
const start = () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
sendPresence(true);
|
||||
heartbeatRef.current = setInterval(() => {
|
||||
if (document.visibilityState === 'visible') sendPresence(true);
|
||||
}, 30000);
|
||||
}
|
||||
};
|
||||
|
||||
const onVisibility = () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
sendPresence(true);
|
||||
if (!heartbeatRef.current) heartbeatRef.current = setInterval(() => sendPresence(true), 30000);
|
||||
} else {
|
||||
sendPresence(false);
|
||||
clearInterval(heartbeatRef.current);
|
||||
heartbeatRef.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
document.addEventListener('visibilitychange', onVisibility);
|
||||
return () => {
|
||||
sendPresence(false);
|
||||
clearInterval(heartbeatRef.current);
|
||||
document.removeEventListener('visibilitychange', onVisibility);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!showPicker) return;
|
||||
|
||||
Reference in New Issue
Block a user