Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions lib/background/background.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ Future<void> serviceMain(ServiceInstance service) async {

final Map<String, Map<String, dynamic>> activeSubscriptions = {};
final nostrService = NostrService();
final db = await openMostroDatabase('events.db');
final eventStore = EventStorage(db: db);

// Register event handlers BEFORE awaiting database open to avoid
// losing events (e.g. 'start' invoked by FCM handler during db init).
service.on('app-foreground-status').listen((data) {
isAppForeground = data?['is-foreground'] ?? isAppForeground;
});

service.on('fcm-wake').listen((data) {
// Service is already running with active subscriptions.
// Nostr subscriptions will automatically receive new events.
logger?.d('FCM wake signal received - subscriptions already active');
});

service.on('start').listen((data) async {
if (data == null) return;

Expand All @@ -50,6 +56,9 @@ Future<void> serviceMain(ServiceInstance service) async {
service.invoke('service-ready', {});
});

final db = await openMostroDatabase('events.db');
final eventStore = EventStorage(db: db);

service.on('update-settings').listen((data) async {
if (data == null) return;

Expand Down
35 changes: 34 additions & 1 deletion lib/services/fcm_service.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:mostro_mobile/data/models/enums/storage_keys.dart';
import 'package:mostro_mobile/services/logger_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:mostro_mobile/firebase_options.dart';
Expand Down Expand Up @@ -45,8 +47,39 @@ Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
final service = FlutterBackgroundService();
final isRunning = await service.isRunning();

if (!isRunning) {
if (isRunning) {
// Service is already running — signal it that FCM detected new activity
service.invoke('fcm-wake', {});
} else {
// Service is dead — start it and send settings
await sharedPrefs.setBool('fcm.pending_fetch', true);
await service.startService();

final settingsJson = await sharedPrefs.getString(
SharedPreferencesKeys.appSettings.value,
);
if (settingsJson != null) {
Map<String, dynamic>? settings;
try {
settings = jsonDecode(settingsJson) as Map<String, dynamic>?;
} catch (e) {
debugPrint('FCM: Failed to decode settings: $e');
}

// Wait briefly for service to initialize (FCM handlers must complete quickly)
const maxWait = Duration(seconds: 3);
final deadline = DateTime.now().add(maxWait);
while (!(await service.isRunning())) {
if (DateTime.now().isAfter(deadline)) break;
await Future.delayed(const Duration(milliseconds: 100));
}

if (await service.isRunning() && settings != null) {
service.invoke('start', {
'settings': settings,
});
}
}
}
} catch (e) {
debugPrint('FCM: background service error: $e');
Expand Down