feat: basic test web notifications using PWA
This commit is contained in:
parent
cedea7fbb0
commit
b2a4ffeb9b
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
||||
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
||||
43
ios/Podfile
Normal file
43
ios/Podfile
Normal file
@ -0,0 +1,43 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '12.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_ios_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
target 'RunnerTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
end
|
||||
end
|
||||
74
lib/firebase_options.dart
Normal file
74
lib/firebase_options.dart
Normal file
@ -0,0 +1,74 @@
|
||||
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
|
||||
import 'package:flutter/foundation.dart'
|
||||
show defaultTargetPlatform, kIsWeb, TargetPlatform;
|
||||
|
||||
class DefaultFirebaseOptions {
|
||||
static FirebaseOptions get currentPlatform {
|
||||
if (kIsWeb) {
|
||||
return web;
|
||||
}
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return android;
|
||||
case TargetPlatform.iOS:
|
||||
return ios;
|
||||
case TargetPlatform.macOS:
|
||||
return macos;
|
||||
case TargetPlatform.windows:
|
||||
return windows;
|
||||
case TargetPlatform.linux:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for linux - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
default:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions are not supported for this platform.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static const FirebaseOptions web = FirebaseOptions(
|
||||
apiKey: 'AIzaSyB5C-HmErqNFRlJwM4S4wfs-arMkJRVmGA',
|
||||
appId: '1:865533380916:web:46725564ea0e1d4e70fd61',
|
||||
messagingSenderId: '865533380916',
|
||||
projectId: 'wesalapp-bc676',
|
||||
authDomain: 'wesalapp-bc676.firebaseapp.com',
|
||||
storageBucket: 'wesalapp-bc676.firebasestorage.app',
|
||||
measurementId: 'G-V4BQJQB24E',
|
||||
);
|
||||
|
||||
static const FirebaseOptions android = FirebaseOptions(
|
||||
apiKey: 'AIzaSyB5C-HmErqNFRlJwM4S4wfs-arMkJRVmGA',
|
||||
appId: '1:865533380916:android:46725564ea0e1d4e70fd61',
|
||||
messagingSenderId: '865533380916',
|
||||
projectId: 'wesalapp-bc676',
|
||||
storageBucket: 'wesalapp-bc676.firebasestorage.app',
|
||||
);
|
||||
|
||||
static const FirebaseOptions ios = FirebaseOptions(
|
||||
apiKey: 'AIzaSyB5C-HmErqNFRlJwM4S4wfs-arMkJRVmGA',
|
||||
appId: '1:865533380916:ios:46725564ea0e1d4e70fd61',
|
||||
messagingSenderId: '865533380916',
|
||||
projectId: 'wesalapp-bc676',
|
||||
storageBucket: 'wesalapp-bc676.firebasestorage.app',
|
||||
iosBundleId: 'com.example.wesalApp',
|
||||
);
|
||||
|
||||
static const FirebaseOptions macos = FirebaseOptions(
|
||||
apiKey: 'AIzaSyB5C-HmErqNFRlJwM4S4wfs-arMkJRVmGA',
|
||||
appId: '1:865533380916:macos:46725564ea0e1d4e70fd61',
|
||||
messagingSenderId: '865533380916',
|
||||
projectId: 'wesalapp-bc676',
|
||||
storageBucket: 'wesalapp-bc676.firebasestorage.app',
|
||||
iosBundleId: 'com.example.wesalApp',
|
||||
);
|
||||
|
||||
static const FirebaseOptions windows = FirebaseOptions(
|
||||
apiKey: 'AIzaSyB5C-HmErqNFRlJwM4S4wfs-arMkJRVmGA',
|
||||
appId: '1:865533380916:windows:46725564ea0e1d4e70fd61',
|
||||
messagingSenderId: '865533380916',
|
||||
projectId: 'wesalapp-bc676',
|
||||
storageBucket: 'wesalapp-bc676.firebasestorage.app',
|
||||
);
|
||||
}
|
||||
@ -1,7 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'firebase_options.dart';
|
||||
import 'screens/home_screen.dart';
|
||||
import 'services/notification_service.dart';
|
||||
|
||||
void main() {
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
);
|
||||
|
||||
await NotificationService().initialize();
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../services/notification_service.dart';
|
||||
|
||||
class FeedPage extends StatefulWidget {
|
||||
@override
|
||||
@ -105,6 +106,17 @@ class _FeedPageState extends State<FeedPage> {
|
||||
},
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () async {
|
||||
final token = await NotificationService().getToken();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('FCM Token: ${token ?? "Not available"}')),
|
||||
);
|
||||
},
|
||||
backgroundColor: Color(0xFF6A4C93),
|
||||
child: Icon(Icons.notifications, color: Colors.white),
|
||||
tooltip: 'Show FCM Token',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
163
lib/services/notification_service.dart
Normal file
163
lib/services/notification_service.dart
Normal file
@ -0,0 +1,163 @@
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class NotificationService {
|
||||
static final NotificationService _instance = NotificationService._internal();
|
||||
factory NotificationService() => _instance;
|
||||
NotificationService._internal();
|
||||
|
||||
FirebaseMessaging? _messaging;
|
||||
|
||||
static const String vapidKey = 'BKrFSFm2cb2DNtEpTNmEy3acpi2ziRA5DhzKSyjshqAWANaoydztUTa0Cn3jwh1v7KN6pHUQfsODFXUWrKG6aSU';
|
||||
|
||||
static const List<String> topics = [
|
||||
'all',
|
||||
'newposts',
|
||||
'newinvites',
|
||||
'invitesfollowup',
|
||||
'appnews',
|
||||
];
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (!kIsWeb) {
|
||||
print('Notifications are only supported on web platform');
|
||||
return;
|
||||
}
|
||||
|
||||
_messaging = FirebaseMessaging.instance;
|
||||
|
||||
await _requestPermission();
|
||||
await _subscribeToTopics();
|
||||
await _setupMessageHandlers();
|
||||
}
|
||||
|
||||
Future<void> _requestPermission() async {
|
||||
if (_messaging == null) return;
|
||||
|
||||
NotificationSettings settings = await _messaging!.requestPermission(
|
||||
alert: true,
|
||||
announcement: false,
|
||||
badge: true,
|
||||
carPlay: false,
|
||||
criticalAlert: false,
|
||||
provisional: false,
|
||||
sound: true,
|
||||
);
|
||||
|
||||
print('User granted permission: ${settings.authorizationStatus}');
|
||||
|
||||
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
|
||||
print('User granted permission for notifications');
|
||||
} else if (settings.authorizationStatus == AuthorizationStatus.provisional) {
|
||||
print('User granted provisional permission for notifications');
|
||||
} else {
|
||||
print('User declined or has not accepted permission for notifications');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _subscribeToTopics() async {
|
||||
if (_messaging == null) return;
|
||||
|
||||
for (String topic in topics) {
|
||||
try {
|
||||
await _messaging!.subscribeToTopic(topic);
|
||||
print('Subscribed to topic: $topic');
|
||||
} catch (e) {
|
||||
print('Error subscribing to topic $topic: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _setupMessageHandlers() async {
|
||||
if (_messaging == null) return;
|
||||
|
||||
// Handle foreground messages
|
||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||
print('Got a message whilst in the foreground!');
|
||||
print('Message data: ${message.data}');
|
||||
|
||||
if (message.notification != null) {
|
||||
print('Message also contained a notification: ${message.notification}');
|
||||
_showNotification(message.notification!);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle background messages
|
||||
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
||||
|
||||
// Handle notification taps
|
||||
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
|
||||
print('A new onMessageOpenedApp event was published!');
|
||||
print('Message data: ${message.data}');
|
||||
_handleNotificationTap(message);
|
||||
});
|
||||
|
||||
// Get the initial message if the app was opened from a notification
|
||||
RemoteMessage? initialMessage = await _messaging!.getInitialMessage();
|
||||
if (initialMessage != null) {
|
||||
print('App opened from notification: ${initialMessage.data}');
|
||||
_handleNotificationTap(initialMessage);
|
||||
}
|
||||
|
||||
// Get the FCM token for this device
|
||||
String? token = await _messaging!.getToken(vapidKey: vapidKey);
|
||||
print('FCM Token: $token');
|
||||
}
|
||||
|
||||
void _showNotification(RemoteNotification notification) {
|
||||
// For web, we rely on the service worker to show notifications
|
||||
// This is mainly for logging and debugging
|
||||
print('Notification Title: ${notification.title}');
|
||||
print('Notification Body: ${notification.body}');
|
||||
}
|
||||
|
||||
void _handleNotificationTap(RemoteMessage message) {
|
||||
// Handle notification tap actions here
|
||||
print('Notification tapped: ${message.data}');
|
||||
|
||||
// You can navigate to specific screens based on the notification data
|
||||
// For example:
|
||||
// if (message.data['type'] == 'newpost') {
|
||||
// // Navigate to posts screen
|
||||
// } else if (message.data['type'] == 'newinvite') {
|
||||
// // Navigate to invitations screen
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> unsubscribeFromTopic(String topic) async {
|
||||
if (_messaging == null) return;
|
||||
|
||||
try {
|
||||
await _messaging!.unsubscribeFromTopic(topic);
|
||||
print('Unsubscribed from topic: $topic');
|
||||
} catch (e) {
|
||||
print('Error unsubscribing from topic $topic: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> subscribeToTopic(String topic) async {
|
||||
if (_messaging == null) return;
|
||||
|
||||
try {
|
||||
await _messaging!.subscribeToTopic(topic);
|
||||
print('Subscribed to topic: $topic');
|
||||
} catch (e) {
|
||||
print('Error subscribing to topic $topic: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> getToken() async {
|
||||
if (_messaging == null) return null;
|
||||
return await _messaging!.getToken(vapidKey: vapidKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Background message handler must be a top-level function
|
||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
print('Handling a background message: ${message.messageId}');
|
||||
print('Message data: ${message.data}');
|
||||
|
||||
if (message.notification != null) {
|
||||
print('Background message contained a notification: ${message.notification}');
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||
|
||||
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||
|
||||
@ -5,6 +5,10 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import firebase_core
|
||||
import firebase_messaging
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
||||
}
|
||||
|
||||
42
macos/Podfile
Normal file
42
macos/Podfile
Normal file
@ -0,0 +1,42 @@
|
||||
platform :osx, '10.14'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_macos_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
|
||||
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||
target 'RunnerTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_macos_build_settings(target)
|
||||
end
|
||||
end
|
||||
79
pubspec.lock
79
pubspec.lock
@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_flutterfire_internals:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _flutterfire_internals
|
||||
sha256: a5788040810bd84400bc209913fbc40f388cded7cdf95ee2f5d2bff7e38d5241
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.58"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -57,6 +65,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_core
|
||||
sha256: c6e8a6bf883d8ddd0dec39be90872daca65beaa6f4cff0051ed3b16c56b82e9f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.15.1"
|
||||
firebase_core_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_platform_interface
|
||||
sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
firebase_core_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_web
|
||||
sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.24.1"
|
||||
firebase_messaging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_messaging
|
||||
sha256: "0f3363f97672eb9f65609fa00ed2f62cc8ec93e7e2d4def99726f9165d3d8a73"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.2.9"
|
||||
firebase_messaging_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_messaging_platform_interface
|
||||
sha256: "7a05ef119a14c5f6a9440d1e0223bcba20c8daf555450e119c4c477bf2c3baa9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.6.9"
|
||||
firebase_messaging_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_messaging_web
|
||||
sha256: a4547f76da2a905190f899eb4d0150e1d0fd52206fce469d9f05ae15bb68b2c5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.10.9"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -75,6 +131,11 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -139,6 +200,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -208,6 +277,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.0.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
sdks:
|
||||
dart: ">=3.8.1 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
flutter: ">=3.22.0"
|
||||
|
||||
@ -10,6 +10,8 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: ^1.0.8
|
||||
firebase_core: ^3.15.1
|
||||
firebase_messaging: ^15.2.9
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
109
web/firebase-messaging-sw.js
Normal file
109
web/firebase-messaging-sw.js
Normal file
@ -0,0 +1,109 @@
|
||||
importScripts('https://www.gstatic.com/firebasejs/9.19.1/firebase-app-compat.js');
|
||||
importScripts('https://www.gstatic.com/firebasejs/9.19.1/firebase-messaging-compat.js');
|
||||
|
||||
// Firebase configuration
|
||||
const firebaseConfig = {
|
||||
apiKey: "AIzaSyB5C-HmErqNFRlJwM4S4wfs-arMkJRVmGA",
|
||||
authDomain: "wesalapp-bc676.firebaseapp.com",
|
||||
projectId: "wesalapp-bc676",
|
||||
storageBucket: "wesalapp-bc676.firebasestorage.app",
|
||||
messagingSenderId: "865533380916",
|
||||
appId: "1:865533380916:web:46725564ea0e1d4e70fd61",
|
||||
measurementId: "G-V4BQJQB24E"
|
||||
};
|
||||
|
||||
// Initialize Firebase
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
|
||||
// Initialize Firebase Messaging
|
||||
const messaging = firebase.messaging();
|
||||
|
||||
// Handle background messages
|
||||
messaging.onBackgroundMessage((payload) => {
|
||||
console.log('Received background message ', payload);
|
||||
|
||||
const notificationTitle = payload.notification?.title || 'Wesal App';
|
||||
const notificationOptions = {
|
||||
body: payload.notification?.body || 'You have a new notification',
|
||||
icon: '/icons/Icon-192.png',
|
||||
badge: '/icons/Icon-192.png',
|
||||
data: payload.data,
|
||||
tag: payload.data?.type || 'general',
|
||||
requireInteraction: true,
|
||||
actions: [
|
||||
{
|
||||
action: 'open',
|
||||
title: 'Open App',
|
||||
},
|
||||
{
|
||||
action: 'close',
|
||||
title: 'Close',
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return self.registration.showNotification(notificationTitle, notificationOptions);
|
||||
});
|
||||
|
||||
// Handle notification clicks
|
||||
self.addEventListener('notificationclick', (event) => {
|
||||
console.log('Notification clicked:', event);
|
||||
|
||||
event.notification.close();
|
||||
|
||||
if (event.action === 'close') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle notification click - open the app
|
||||
event.waitUntil(
|
||||
clients.matchAll({ type: 'window' }).then((clientList) => {
|
||||
// If the app is already open, focus it
|
||||
for (const client of clientList) {
|
||||
if (client.url === '/' && 'focus' in client) {
|
||||
return client.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, open a new window
|
||||
if (clients.openWindow) {
|
||||
return clients.openWindow('/');
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// Handle push events
|
||||
self.addEventListener('push', (event) => {
|
||||
console.log('Push event received:', event);
|
||||
|
||||
if (event.data) {
|
||||
const data = event.data.json();
|
||||
console.log('Push data:', data);
|
||||
|
||||
const notificationTitle = data.notification?.title || 'Wesal App';
|
||||
const notificationOptions = {
|
||||
body: data.notification?.body || 'You have a new notification',
|
||||
icon: '/icons/Icon-192.png',
|
||||
badge: '/icons/Icon-192.png',
|
||||
data: data.data,
|
||||
tag: data.data?.type || 'general',
|
||||
requireInteraction: true,
|
||||
};
|
||||
|
||||
event.waitUntil(
|
||||
self.registration.showNotification(notificationTitle, notificationOptions)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle service worker activation
|
||||
self.addEventListener('activate', (event) => {
|
||||
console.log('Service worker activated');
|
||||
});
|
||||
|
||||
// Handle service worker installation
|
||||
self.addEventListener('install', (event) => {
|
||||
console.log('Service worker installed');
|
||||
self.skipWaiting();
|
||||
});
|
||||
@ -34,5 +34,20 @@
|
||||
</head>
|
||||
<body>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
|
||||
<!-- Firebase Messaging Service Worker -->
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('/firebase-messaging-sw.js')
|
||||
.then(function(registration) {
|
||||
console.log('Firebase Messaging Service Worker registered successfully:', registration);
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.log('Firebase Messaging Service Worker registration failed:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FirebaseCorePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
firebase_core
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
Loading…
Reference in New Issue
Block a user