push_service.dart 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import 'package:firebase_core/firebase_core.dart';
  2. import 'package:firebase_messaging/firebase_messaging.dart';
  3. import 'package:logging/logging.dart';
  4. import 'package:photos/core/configuration.dart';
  5. import 'package:photos/core/constants.dart';
  6. import 'package:photos/core/event_bus.dart';
  7. import 'package:photos/core/network.dart';
  8. import 'package:photos/events/signed_in_event.dart';
  9. import 'package:photos/services/sync_service.dart';
  10. import 'package:shared_preferences/shared_preferences.dart';
  11. class PushService {
  12. static const kFCMPushToken = "fcm_push_token";
  13. static const kLastFCMTokenUpdationTime = "fcm_push_token_updation_time";
  14. static const kFCMTokenUpdationIntervalInMicroSeconds = 30 * microSecondsInDay;
  15. static const kPushAction = "action";
  16. static const kSync = "sync";
  17. static final PushService instance = PushService._privateConstructor();
  18. static final _logger = Logger("PushService");
  19. late SharedPreferences _prefs;
  20. PushService._privateConstructor();
  21. Future<void> init() async {
  22. _prefs = await SharedPreferences.getInstance();
  23. await Firebase.initializeApp();
  24. FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  25. _logger.info("Got a message whilst in the foreground!");
  26. _handleForegroundPushMessage(message);
  27. });
  28. try {
  29. if (Configuration.instance.hasConfiguredAccount()) {
  30. await _configurePushToken();
  31. } else {
  32. Bus.instance.on<SignedInEvent>().listen((_) async {
  33. _configurePushToken();
  34. });
  35. }
  36. } catch (e, s) {
  37. _logger.severe("Could not configure push token", e, s);
  38. }
  39. }
  40. Future<void> _configurePushToken() async {
  41. final String? fcmToken = await FirebaseMessaging.instance.getToken();
  42. final shouldForceRefreshServerToken =
  43. DateTime.now().microsecondsSinceEpoch -
  44. (_prefs.getInt(kLastFCMTokenUpdationTime) ?? 0) >
  45. kFCMTokenUpdationIntervalInMicroSeconds;
  46. if (fcmToken != null &&
  47. (_prefs.getString(kFCMPushToken) != fcmToken ||
  48. shouldForceRefreshServerToken)) {
  49. final String? apnsToken = await FirebaseMessaging.instance.getAPNSToken();
  50. try {
  51. _logger.info("Updating token on server");
  52. await _setPushTokenOnServer(fcmToken, apnsToken);
  53. await _prefs.setString(kFCMPushToken, fcmToken);
  54. await _prefs.setInt(
  55. kLastFCMTokenUpdationTime,
  56. DateTime.now().microsecondsSinceEpoch,
  57. );
  58. _logger.info("Push token updated on server");
  59. } catch (e) {
  60. _logger.severe("Could not set push token", e, StackTrace.current);
  61. }
  62. } else {
  63. _logger.info("Skipping token update");
  64. }
  65. }
  66. Future<void> _setPushTokenOnServer(
  67. String fcmToken,
  68. String? apnsToken,
  69. ) async {
  70. await Network.instance.enteDio.post(
  71. "/push/token",
  72. data: {
  73. "fcmToken": fcmToken,
  74. "apnsToken": apnsToken,
  75. },
  76. );
  77. }
  78. void _handleForegroundPushMessage(RemoteMessage message) {
  79. _logger.info("Message data: ${message.data}");
  80. if (message.notification != null) {
  81. _logger.info(
  82. "Message also contained a notification: ${message.notification}",
  83. );
  84. }
  85. if (shouldSync(message)) {
  86. SyncService.instance.sync();
  87. }
  88. }
  89. static bool shouldSync(RemoteMessage message) {
  90. return message.data.containsKey(kPushAction) &&
  91. message.data[kPushAction] == kSync;
  92. }
  93. }