- LoginViewModel now calls Tasks.await(FirebaseMessaging.getInstance().token)
to actively fetch the FCM token if not yet saved in prefs
- Previous code relied solely on onNewToken callback, which may not fire
before the user logs in on a fresh install
- FCMService now supports both HTTP v1 API (service account) and legacy API (server key)
- v1 API uses OAuth2 JWT auth with Firebase service account; tries this first
- Falls back to legacy HTTP API if only server key is configured
- Removes invalid tokens from DB automatically (NotRegistered, INVALID_ARGUMENT, etc.)
- AdminController now logs push result status and shows in UI response
- .env updated with FCM_SERVER_KEY placeholder and docs
- Migration 010 run in dev
- google-services.json now has real Firebase project values
- Added firebase-messaging-ktx dependency (was missing)
- Updated google-services plugin to 4.4.4
Backend:
- New user_fcm_tokens table (migration 010) for storing device tokens
- FCMService sends push via Firebase HTTP legacy API (server key from .env)
- POST /api/fcm/register endpoint for Android to register its FCM token
- AdminController::sendNotification() triggers FCM push after DB insert
- FCM config added to config.php
Android:
- Firebase Cloud Messaging service (ServerManagerFirebaseService)
receives push notifications and shows them via NotificationHelper
- FCM token registered with backend on new token and on login
- google-services.json template (must be replaced with real Firebase config)
- firebase-setup.sh script with configuration instructions
- FCM dependency + google-services plugin added to Gradle
- Bump to v1.8.0 (versionCode 12)
- LoginViewModel now calls Tasks.await(FirebaseMessaging.getInstance().token)
to actively fetch the FCM token if not yet saved in prefs
- Previous code relied solely on onNewToken callback, which may not fire
before the user logs in on a fresh install
- FCMService now supports both HTTP v1 API (service account) and legacy API (server key)
- v1 API uses OAuth2 JWT auth with Firebase service account; tries this first
- Falls back to legacy HTTP API if only server key is configured
- Removes invalid tokens from DB automatically (NotRegistered, INVALID_ARGUMENT, etc.)
- AdminController now logs push result status and shows in UI response
- .env updated with FCM_SERVER_KEY placeholder and docs
- Migration 010 run in dev
- google-services.json now has real Firebase project values
- Added firebase-messaging-ktx dependency (was missing)
- Updated google-services plugin to 4.4.4
Backend:
- New user_fcm_tokens table (migration 010) for storing device tokens
- FCMService sends push via Firebase HTTP legacy API (server key from .env)
- POST /api/fcm/register endpoint for Android to register its FCM token
- AdminController::sendNotification() triggers FCM push after DB insert
- FCM config added to config.php
Android:
- Firebase Cloud Messaging service (ServerManagerFirebaseService)
receives push notifications and shows them via NotificationHelper
- FCM token registered with backend on new token and on login
- google-services.json template (must be replaced with real Firebase config)
- firebase-setup.sh script with configuration instructions
- FCM dependency + google-services plugin added to Gradle
- Bump to v1.8.0 (versionCode 12)
- is_read and read_at columns are now obsolete since notification_reads
tracks per-user read receipts
- Removed UPDATE statements in markAsRead/markAllAsRead that touched
the old columns
- API response still includes computed is_read field via SQL CASE in
getForUser() JOIN with notification_reads, maintaining Android
compatibility
- Migration 009 drops both columns
- New notification_reads table (migration 008) with unique (notification_id, user_id)
- Notification model: markAsRead inserts into notification_reads; getForUser JOINs
to show per-user read status; getUnreadCount checks NOT EXISTS in reads table
- getAll() includes read_count subquery for admin view
- Admin view shows 'X / Y' read count for broadcast notifications,
'Read'/'Unread' badge for user-targeted ones
- Migrates existing read notifications into notification_reads
- AGENTS.md updated with new conventions
- Removed the local old() function definition from views/servers/create.php
which conflicted with the global old() in src/Helpers/functions.php:37
- Replaced all old() calls with direct htmlspecialchars([...]) lookups