1"use strict"; 2 3class FirebaseAppManager { 4 constructor(config) { 5 if (!config || typeof config !== 'object') { 6 throw new Error('Firebase config object is required'); 7 } 8 9 this.firebaseConfig = config; 10 this.app = null; 11 this.messaging = null; 12 } 13 14 initialize() { 15 try { 16 if (firebase.apps.length === 0) { 17 this.app = firebase.initializeApp(this.firebaseConfig); 18 // 'â Firebase initialized'; 19 } else { 20 this.app = firebase.app(); 21 // 'â ï¸ Firebase already initialized'; 22 } 23 24 if (firebase.messaging.isSupported && firebase.messaging.isSupported()) { 25 this.messaging = firebase.messaging(); 26 // 'ð© Firebase messaging initialized'; 27 } 28 } catch (e) { 29 console.warn('ð¥ Firebase initialization failed:', e); 30 } 31 } 32 33 getApp() { 34 return this.app; 35 } 36 37 getMessaging() { 38 return this.messaging; 39 } 40} 41 42let firebaseConfigurationConfig = $('#Firebase_Configuration_Config'); 43const firebaseManager = new FirebaseAppManager({ 44 apiKey: firebaseConfigurationConfig.data('api-key'), 45 authDomain: firebaseConfigurationConfig.data('auth-domain'), 46 projectId: firebaseConfigurationConfig.data('project-id'), 47 storageBucket: firebaseConfigurationConfig.data('storage-bucket'), 48 messagingSenderId: firebaseConfigurationConfig.data('messaging-sender-id'), 49 appId: firebaseConfigurationConfig.data('app-id'), 50 measurementId: firebaseConfigurationConfig.data('measurement-id') 51}); 52 53firebaseManager.initialize(); 54 55const app = firebaseManager.getApp(); 56const messaging = firebaseManager.getMessaging(); 57 58 59function requestNotificationPermission() { 60 return Notification.requestPermission().then(permission => { 61 if (permission === 'granted') { 62 return true; 63 } else { 64 console.warn('Notification permission denied.'); 65 return false; 66 } 67 }); 68} 69 70function subscribeToNotificationTopics(topics) { 71 requestNotificationPermission().then(permissionGranted => { 72 if (permissionGranted) { 73 messaging.getToken().then(token => { 74 topics.forEach(topic => { 75 subscribeTokenToBackend(token, topic); 76 }); 77 }).catch(error => { 78 console.warn('Error getting token:', error); 79 }); 80 } 81 }); 82} 83 84function subscribeTokenToBackend(token, topic) { 85 fetch(firebaseConfigurationConfig.data('route'), { 86 method: 'POST', 87 headers: { 88 'Content-Type': 'application/json', 89 'X-CSRF-TOKEN': firebaseConfigurationConfig.data('csrf-token') 90 }, 91 body: JSON.stringify({ 92 token: token, 93 topic: topic 94 }) 95 }).then(response => { 96 if (response.status < 200 || response.status >= 400) { 97 return response.text().then(text => { 98 throw new Error(`Error subscribing to topic: ${response.status} - ${text}`); 99 }); 100 } 101 }).catch(error => { 102 console.warn('Subscription error:', error); 103 }); 104} 105 106function displayNotification(notification) { 107 const options = { 108 body: notification.body, 109 icon: $('#Firebase_Configuration_Config').data('favicon'), 110 }; 111 new Notification(notification.title, options); 112} 113 114 115messaging.onMessage(function (payload) { 116 if (payload?.data?.type?.includes('product_restock')) { 117 productRestockStockLimitStatus(payload.data); 118 } 119 120 if (payload.data) { 121 displayNotification(payload.data); 122 } 123}); 124 125// Deletes the browser's FCM registration token so the server stops delivering 126// push notifications to this device after the current user logs out. 127// Called by logout link interceptors before navigating away. 128function clearFcmToken() { 129 if (!messaging) return Promise.resolve(); 130 return messaging.deleteToken().catch(function (e) { 131 console.warn('[FCM] deleteToken failed:', e); 132 }); 133}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.