Fix: Push-Registrierung griff nicht bei bereits eingeloggtem Nutzer
registerDevice lief nur bei Auth-Änderungen (ref.listen) – bestand der Login schon beim App-Start, wurde nie ein FCM-Token gespeichert. Jetzt reaktiv über pushSetupProvider (ref.watch). Zusätzlich: temporäre debugReminders-Function zur Diagnose der Push-Strecke. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0ce4b2cb19
commit
4bceb8747b
4 changed files with 82 additions and 7 deletions
68
functions/src/debug.ts
Normal file
68
functions/src/debug.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import {onRequest} from "firebase-functions/v2/https";
|
||||||
|
import * as admin from "firebase-admin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEMPORÄRE Diagnose-Funktion für die Push-Strecke. Wird nach dem Debugging
|
||||||
|
* wieder entfernt. Zugriff nur mit zufälligem Token (kein Erraten möglich);
|
||||||
|
* gibt keine sensiblen Inhalte zurück.
|
||||||
|
*
|
||||||
|
* ?mode=diagnose → Zustand aller Nutzer (Tokens, Zeiten, Slot-Rechnung)
|
||||||
|
* ?mode=send → schickt sofort eine Test-Push an alle Nutzer-Tokens
|
||||||
|
*/
|
||||||
|
const DEBUG_TOKEN = "lftm-dbg-xK92mQ7pW4nT";
|
||||||
|
|
||||||
|
export const debugReminders = onRequest(
|
||||||
|
{region: "europe-west3"},
|
||||||
|
async (req, res) => {
|
||||||
|
if (req.query.token !== DEBUG_TOKEN) {
|
||||||
|
res.status(403).send("forbidden");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const db = admin.firestore();
|
||||||
|
const now = new Date();
|
||||||
|
const users = await db.collection("users").get();
|
||||||
|
const report: unknown[] = [];
|
||||||
|
|
||||||
|
for (const userDoc of users.docs) {
|
||||||
|
const user = userDoc.data();
|
||||||
|
const tokens: string[] = user.fcmTokens ?? [];
|
||||||
|
const timezone: string = user.timezone ?? "Europe/Berlin";
|
||||||
|
const reminderTime: string = user.reminderTime ?? "09:00";
|
||||||
|
|
||||||
|
const local = new Intl.DateTimeFormat("en-GB", {
|
||||||
|
timeZone: timezone,
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
hour12: false,
|
||||||
|
}).format(now);
|
||||||
|
|
||||||
|
const entry: Record<string, unknown> = {
|
||||||
|
uid: userDoc.id,
|
||||||
|
tokenCount: tokens.length,
|
||||||
|
tokenPreviews: tokens.map((t) => t.slice(0, 12) + "…"),
|
||||||
|
reminderTime,
|
||||||
|
timezone,
|
||||||
|
localNow: local,
|
||||||
|
householdId: user.householdId ?? null,
|
||||||
|
lastReminderSentOn: user.lastReminderSentOn ?? null,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (req.query.mode === "send" && tokens.length > 0) {
|
||||||
|
const response = await admin.messaging().sendEachForMulticast({
|
||||||
|
tokens,
|
||||||
|
notification: {
|
||||||
|
title: "Test-Push von LeafItToMe 🌱",
|
||||||
|
body: "Wenn du das liest, funktioniert die Push-Strecke.",
|
||||||
|
},
|
||||||
|
apns: {payload: {aps: {sound: "default"}}},
|
||||||
|
android: {notification: {defaultSound: true}, priority: "high"},
|
||||||
|
});
|
||||||
|
entry.sendResults = response.responses.map((r) =>
|
||||||
|
r.success ? "ok" : `${r.error?.code}: ${r.error?.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
report.push(entry);
|
||||||
|
}
|
||||||
|
res.json({now: now.toISOString(), users: report});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -5,6 +5,7 @@ import * as admin from "firebase-admin";
|
||||||
admin.initializeApp();
|
admin.initializeApp();
|
||||||
|
|
||||||
export {sendDailyReminders} from "./reminders";
|
export {sendDailyReminders} from "./reminders";
|
||||||
|
export {debugReminders} from "./debug";
|
||||||
|
|
||||||
// Secrets liegen im Google Secret Manager (firebase functions:secrets:set),
|
// Secrets liegen im Google Secret Manager (firebase functions:secrets:set),
|
||||||
// niemals im Code oder in der App.
|
// niemals im Code oder in der App.
|
||||||
|
|
|
||||||
10
lib/app.dart
10
lib/app.dart
|
|
@ -16,13 +16,9 @@ class LeafItToMeApp extends ConsumerWidget {
|
||||||
final settings = ref.watch(settingsProvider);
|
final settings = ref.watch(settingsProvider);
|
||||||
final router = ref.watch(appRouterProvider);
|
final router = ref.watch(appRouterProvider);
|
||||||
|
|
||||||
// Nach jedem Login das Gerät für Push-Erinnerungen registrieren.
|
// Hält die Push-Registrierung aktiv: registriert das Gerät, sobald ein
|
||||||
ref.listen(authStateProvider, (previous, next) {
|
// Nutzer angemeldet ist (auch wenn der Login vor dem App-Start bestand).
|
||||||
final user = next.value;
|
ref.watch(pushSetupProvider);
|
||||||
if (user != null) {
|
|
||||||
ref.read(pushRegistrationServiceProvider).registerDevice(user);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
routerConfig: router,
|
routerConfig: router,
|
||||||
|
|
|
||||||
|
|
@ -71,3 +71,13 @@ final pushRegistrationServiceProvider = Provider<PushRegistrationService>((ref)
|
||||||
ref.watch(firebaseAuthProvider),
|
ref.watch(firebaseAuthProvider),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Sorgt dafür, dass das Gerät registriert ist, sobald (und solange) ein
|
||||||
|
/// Nutzer angemeldet ist — auch wenn der Login schon vor dem App-Start
|
||||||
|
/// bestand. Wird in app.dart per ref.watch aktiv gehalten.
|
||||||
|
final pushSetupProvider = Provider<void>((ref) {
|
||||||
|
final user = ref.watch(authStateProvider).value;
|
||||||
|
if (user != null) {
|
||||||
|
ref.read(pushRegistrationServiceProvider).registerDevice(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue