browser-extension-manager 1.0.13 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/CLAUDE.md +672 -0
  3. package/TODO.md +3 -0
  4. package/dist/assets/css/browser-extension-manager.scss +18 -0
  5. package/dist/assets/css/components/content/index.scss +5 -0
  6. package/dist/assets/css/components/options/index.scss +5 -0
  7. package/dist/assets/css/components/pages/index.scss +5 -0
  8. package/dist/assets/css/components/popup/index.scss +5 -0
  9. package/dist/assets/css/core/_animations.scss +64 -0
  10. package/dist/assets/css/core/_initialize.scss +23 -0
  11. package/dist/assets/css/core/_utilities.scss +80 -0
  12. package/dist/assets/themes/_template/_theme.js +5 -0
  13. package/dist/assets/themes/_template/_theme.scss +5 -0
  14. package/dist/assets/themes/bootstrap/_theme.js +16 -0
  15. package/dist/assets/themes/bootstrap/_theme.scss +232 -0
  16. package/dist/assets/themes/bootstrap/js/index.esm.js +19 -0
  17. package/dist/assets/themes/bootstrap/js/index.umd.js +34 -0
  18. package/dist/assets/themes/bootstrap/js/src/alert.js +87 -0
  19. package/dist/assets/themes/bootstrap/js/src/base-component.js +86 -0
  20. package/dist/assets/themes/bootstrap/js/src/button.js +72 -0
  21. package/dist/assets/themes/bootstrap/js/src/carousel.js +474 -0
  22. package/dist/assets/themes/bootstrap/js/src/collapse.js +297 -0
  23. package/dist/assets/themes/bootstrap/js/src/dom/data.js +55 -0
  24. package/dist/assets/themes/bootstrap/js/src/dom/event-handler.js +317 -0
  25. package/dist/assets/themes/bootstrap/js/src/dom/manipulator.js +71 -0
  26. package/dist/assets/themes/bootstrap/js/src/dom/selector-engine.js +126 -0
  27. package/dist/assets/themes/bootstrap/js/src/dropdown.js +458 -0
  28. package/dist/assets/themes/bootstrap/js/src/modal.js +378 -0
  29. package/dist/assets/themes/bootstrap/js/src/offcanvas.js +282 -0
  30. package/dist/assets/themes/bootstrap/js/src/popover.js +97 -0
  31. package/dist/assets/themes/bootstrap/js/src/scrollspy.js +296 -0
  32. package/dist/assets/themes/bootstrap/js/src/tab.js +315 -0
  33. package/dist/assets/themes/bootstrap/js/src/toast.js +224 -0
  34. package/dist/assets/themes/bootstrap/js/src/tooltip.js +632 -0
  35. package/dist/assets/themes/bootstrap/js/src/util/backdrop.js +151 -0
  36. package/dist/assets/themes/bootstrap/js/src/util/component-functions.js +35 -0
  37. package/dist/assets/themes/bootstrap/js/src/util/config.js +65 -0
  38. package/dist/assets/themes/bootstrap/js/src/util/focustrap.js +115 -0
  39. package/dist/assets/themes/bootstrap/js/src/util/index.js +306 -0
  40. package/dist/assets/themes/bootstrap/js/src/util/sanitizer.js +117 -0
  41. package/dist/assets/themes/bootstrap/js/src/util/scrollbar.js +114 -0
  42. package/dist/assets/themes/bootstrap/js/src/util/swipe.js +146 -0
  43. package/dist/assets/themes/bootstrap/js/src/util/template-factory.js +160 -0
  44. package/dist/assets/themes/bootstrap/scss/_accordion.scss +153 -0
  45. package/dist/assets/themes/bootstrap/scss/_alert.scss +68 -0
  46. package/dist/assets/themes/bootstrap/scss/_badge.scss +38 -0
  47. package/dist/assets/themes/bootstrap/scss/_breadcrumb.scss +40 -0
  48. package/dist/assets/themes/bootstrap/scss/_button-group.scss +147 -0
  49. package/dist/assets/themes/bootstrap/scss/_buttons.scss +216 -0
  50. package/dist/assets/themes/bootstrap/scss/_card.scss +238 -0
  51. package/dist/assets/themes/bootstrap/scss/_carousel.scss +226 -0
  52. package/dist/assets/themes/bootstrap/scss/_close.scss +66 -0
  53. package/dist/assets/themes/bootstrap/scss/_containers.scss +41 -0
  54. package/dist/assets/themes/bootstrap/scss/_dropdown.scss +250 -0
  55. package/dist/assets/themes/bootstrap/scss/_forms.scss +9 -0
  56. package/dist/assets/themes/bootstrap/scss/_functions.scss +302 -0
  57. package/dist/assets/themes/bootstrap/scss/_grid.scss +39 -0
  58. package/dist/assets/themes/bootstrap/scss/_helpers.scss +12 -0
  59. package/dist/assets/themes/bootstrap/scss/_images.scss +42 -0
  60. package/dist/assets/themes/bootstrap/scss/_list-group.scss +199 -0
  61. package/dist/assets/themes/bootstrap/scss/_maps.scss +174 -0
  62. package/dist/assets/themes/bootstrap/scss/_mixins.scss +42 -0
  63. package/dist/assets/themes/bootstrap/scss/_modal.scss +240 -0
  64. package/dist/assets/themes/bootstrap/scss/_nav.scss +197 -0
  65. package/dist/assets/themes/bootstrap/scss/_navbar.scss +289 -0
  66. package/dist/assets/themes/bootstrap/scss/_offcanvas.scss +147 -0
  67. package/dist/assets/themes/bootstrap/scss/_pagination.scss +109 -0
  68. package/dist/assets/themes/bootstrap/scss/_placeholders.scss +51 -0
  69. package/dist/assets/themes/bootstrap/scss/_popover.scss +196 -0
  70. package/dist/assets/themes/bootstrap/scss/_progress.scss +68 -0
  71. package/dist/assets/themes/bootstrap/scss/_reboot.scss +611 -0
  72. package/dist/assets/themes/bootstrap/scss/_root.scss +187 -0
  73. package/dist/assets/themes/bootstrap/scss/_spinners.scss +85 -0
  74. package/dist/assets/themes/bootstrap/scss/_tables.scss +171 -0
  75. package/dist/assets/themes/bootstrap/scss/_toasts.scss +73 -0
  76. package/dist/assets/themes/bootstrap/scss/_tooltip.scss +119 -0
  77. package/dist/assets/themes/bootstrap/scss/_transitions.scss +27 -0
  78. package/dist/assets/themes/bootstrap/scss/_type.scss +106 -0
  79. package/dist/assets/themes/bootstrap/scss/_utilities.scss +806 -0
  80. package/dist/assets/themes/bootstrap/scss/_variables-dark.scss +102 -0
  81. package/dist/assets/themes/bootstrap/scss/_variables.scss +1753 -0
  82. package/dist/assets/themes/bootstrap/scss/bootstrap-grid.scss +62 -0
  83. package/dist/assets/themes/bootstrap/scss/bootstrap-reboot.scss +10 -0
  84. package/dist/assets/themes/bootstrap/scss/bootstrap-utilities.scss +19 -0
  85. package/dist/assets/themes/bootstrap/scss/bootstrap.scss +52 -0
  86. package/dist/assets/themes/bootstrap/scss/forms/_floating-labels.scss +97 -0
  87. package/dist/assets/themes/bootstrap/scss/forms/_form-check.scss +189 -0
  88. package/dist/assets/themes/bootstrap/scss/forms/_form-control.scss +214 -0
  89. package/dist/assets/themes/bootstrap/scss/forms/_form-range.scss +91 -0
  90. package/dist/assets/themes/bootstrap/scss/forms/_form-select.scss +80 -0
  91. package/dist/assets/themes/bootstrap/scss/forms/_form-text.scss +11 -0
  92. package/dist/assets/themes/bootstrap/scss/forms/_input-group.scss +132 -0
  93. package/dist/assets/themes/bootstrap/scss/forms/_labels.scss +36 -0
  94. package/dist/assets/themes/bootstrap/scss/forms/_validation.scss +12 -0
  95. package/dist/assets/themes/bootstrap/scss/helpers/_clearfix.scss +3 -0
  96. package/dist/assets/themes/bootstrap/scss/helpers/_color-bg.scss +7 -0
  97. package/dist/assets/themes/bootstrap/scss/helpers/_colored-links.scss +30 -0
  98. package/dist/assets/themes/bootstrap/scss/helpers/_focus-ring.scss +5 -0
  99. package/dist/assets/themes/bootstrap/scss/helpers/_icon-link.scss +25 -0
  100. package/dist/assets/themes/bootstrap/scss/helpers/_position.scss +36 -0
  101. package/dist/assets/themes/bootstrap/scss/helpers/_ratio.scss +26 -0
  102. package/dist/assets/themes/bootstrap/scss/helpers/_stacks.scss +15 -0
  103. package/dist/assets/themes/bootstrap/scss/helpers/_stretched-link.scss +15 -0
  104. package/dist/assets/themes/bootstrap/scss/helpers/_text-truncation.scss +7 -0
  105. package/dist/assets/themes/bootstrap/scss/helpers/_visually-hidden.scss +8 -0
  106. package/dist/assets/themes/bootstrap/scss/helpers/_vr.scss +8 -0
  107. package/dist/assets/themes/bootstrap/scss/mixins/_alert.scss +18 -0
  108. package/dist/assets/themes/bootstrap/scss/mixins/_backdrop.scss +14 -0
  109. package/dist/assets/themes/bootstrap/scss/mixins/_banner.scss +7 -0
  110. package/dist/assets/themes/bootstrap/scss/mixins/_border-radius.scss +78 -0
  111. package/dist/assets/themes/bootstrap/scss/mixins/_box-shadow.scss +18 -0
  112. package/dist/assets/themes/bootstrap/scss/mixins/_breakpoints.scss +127 -0
  113. package/dist/assets/themes/bootstrap/scss/mixins/_buttons.scss +70 -0
  114. package/dist/assets/themes/bootstrap/scss/mixins/_caret.scss +69 -0
  115. package/dist/assets/themes/bootstrap/scss/mixins/_clearfix.scss +9 -0
  116. package/dist/assets/themes/bootstrap/scss/mixins/_color-mode.scss +21 -0
  117. package/dist/assets/themes/bootstrap/scss/mixins/_color-scheme.scss +7 -0
  118. package/dist/assets/themes/bootstrap/scss/mixins/_container.scss +11 -0
  119. package/dist/assets/themes/bootstrap/scss/mixins/_deprecate.scss +10 -0
  120. package/dist/assets/themes/bootstrap/scss/mixins/_forms.scss +163 -0
  121. package/dist/assets/themes/bootstrap/scss/mixins/_gradients.scss +47 -0
  122. package/dist/assets/themes/bootstrap/scss/mixins/_grid.scss +151 -0
  123. package/dist/assets/themes/bootstrap/scss/mixins/_image.scss +16 -0
  124. package/dist/assets/themes/bootstrap/scss/mixins/_list-group.scss +26 -0
  125. package/dist/assets/themes/bootstrap/scss/mixins/_lists.scss +7 -0
  126. package/dist/assets/themes/bootstrap/scss/mixins/_pagination.scss +10 -0
  127. package/dist/assets/themes/bootstrap/scss/mixins/_reset-text.scss +17 -0
  128. package/dist/assets/themes/bootstrap/scss/mixins/_resize.scss +6 -0
  129. package/dist/assets/themes/bootstrap/scss/mixins/_table-variants.scss +24 -0
  130. package/dist/assets/themes/bootstrap/scss/mixins/_text-truncate.scss +8 -0
  131. package/dist/assets/themes/bootstrap/scss/mixins/_transition.scss +26 -0
  132. package/dist/assets/themes/bootstrap/scss/mixins/_utilities.scss +97 -0
  133. package/dist/assets/themes/bootstrap/scss/mixins/_visually-hidden.scss +38 -0
  134. package/dist/assets/themes/bootstrap/scss/tests/jasmine.js +16 -0
  135. package/dist/assets/themes/bootstrap/scss/tests/mixins/_auto-import-of-variables-dark.test.scss +7 -0
  136. package/dist/assets/themes/bootstrap/scss/tests/mixins/_color-modes.test.scss +69 -0
  137. package/dist/assets/themes/bootstrap/scss/tests/mixins/_media-query-color-mode-full.test.scss +8 -0
  138. package/dist/assets/themes/bootstrap/scss/tests/mixins/_utilities.test.scss +393 -0
  139. package/dist/assets/themes/bootstrap/scss/tests/sass-true/register.js +14 -0
  140. package/dist/assets/themes/bootstrap/scss/tests/sass-true/runner.js +17 -0
  141. package/dist/assets/themes/bootstrap/scss/tests/utilities/_api.test.scss +75 -0
  142. package/dist/assets/themes/bootstrap/scss/utilities/_api.scss +47 -0
  143. package/dist/assets/themes/bootstrap/scss/vendor/_rfs.scss +348 -0
  144. package/dist/assets/themes/classy/README.md +75 -0
  145. package/dist/assets/themes/classy/_config.scss +185 -0
  146. package/dist/assets/themes/classy/_theme.js +29 -0
  147. package/dist/assets/themes/classy/_theme.scss +34 -0
  148. package/dist/assets/themes/classy/css/base/_animations.scss +27 -0
  149. package/dist/assets/themes/classy/css/base/_backgrounds.scss +191 -0
  150. package/dist/assets/themes/classy/css/base/_borders.scss +65 -0
  151. package/dist/assets/themes/classy/css/base/_root.scss +58 -0
  152. package/dist/assets/themes/classy/css/base/_soft-colors.scss +92 -0
  153. package/dist/assets/themes/classy/css/base/_spacing.scss +64 -0
  154. package/dist/assets/themes/classy/css/base/_typography.scss +179 -0
  155. package/dist/assets/themes/classy/css/base/_utilities.scss +77 -0
  156. package/dist/assets/themes/classy/css/components/_accordion.scss +33 -0
  157. package/dist/assets/themes/classy/css/components/_avatars.scss +32 -0
  158. package/dist/assets/themes/classy/css/components/_badges.scss +25 -0
  159. package/dist/assets/themes/classy/css/components/_buttons.scss +397 -0
  160. package/dist/assets/themes/classy/css/components/_cards.scss +33 -0
  161. package/dist/assets/themes/classy/css/components/_carousel.scss +41 -0
  162. package/dist/assets/themes/classy/css/components/_forms.scss +115 -0
  163. package/dist/assets/themes/classy/css/components/_links.scss +19 -0
  164. package/dist/assets/themes/classy/css/components/_logo-scroll.scss +57 -0
  165. package/dist/assets/themes/classy/css/components/_spinners.scss +19 -0
  166. package/dist/assets/themes/classy/css/components/_text.scss +41 -0
  167. package/dist/assets/themes/classy/css/layout/_blog.scss +42 -0
  168. package/dist/assets/themes/classy/css/layout/_general.scss +139 -0
  169. package/dist/assets/themes/classy/css/layout/_navigation.scss +576 -0
  170. package/dist/assets/themes/classy/css/layout/_team.scss +18 -0
  171. package/dist/assets/themes/classy/js/logo-scroll.js +83 -0
  172. package/dist/assets/themes/classy/js/navbar-scroll.js +65 -0
  173. package/dist/background.js +236 -260
  174. package/dist/build.js +93 -4
  175. package/dist/commands/setup.js +0 -268
  176. package/dist/config/manifest.json +11 -3
  177. package/dist/config/page-template.html +21 -0
  178. package/dist/defaults/.nvmrc +1 -1
  179. package/dist/defaults/CLAUDE.md +8 -0
  180. package/dist/defaults/config/browser-extension-manager.json +37 -0
  181. package/dist/defaults/src/assets/css/components/content/index.scss +11 -0
  182. package/dist/defaults/src/assets/css/components/options/index.scss +14 -0
  183. package/dist/defaults/src/assets/css/components/pages/index.scss +10 -0
  184. package/dist/defaults/src/assets/css/components/popup/index.scss +10 -0
  185. package/dist/defaults/src/assets/css/components/sidepanel/index.scss +6 -0
  186. package/dist/defaults/src/assets/css/main.scss +32 -0
  187. package/dist/defaults/src/assets/js/components/background/index.js +22 -0
  188. package/dist/defaults/src/assets/js/components/content/index.js +22 -0
  189. package/dist/defaults/src/assets/js/components/options/index.js +22 -0
  190. package/dist/defaults/src/assets/js/components/pages/index.js +22 -0
  191. package/dist/defaults/src/assets/js/components/popup/index.js +22 -0
  192. package/dist/defaults/src/assets/js/components/sidepanel/index.js +20 -0
  193. package/dist/defaults/src/assets/vendor/.gitkeep +0 -0
  194. package/dist/defaults/src/manifest.json +11 -6
  195. package/dist/defaults/src/views/options/index.html +8 -0
  196. package/dist/defaults/src/views/pages/index.html +10 -0
  197. package/dist/defaults/src/views/popup/index.html +4 -0
  198. package/dist/defaults/src/views/sidepanel/index.html +4 -0
  199. package/dist/gulp/main.js +11 -5
  200. package/dist/gulp/plugins/webpack/strip-dev-blocks.js +53 -0
  201. package/dist/gulp/tasks/{_package.js → BU/_package.js} +1 -1
  202. package/dist/gulp/tasks/{developmentRebuild.js → BU/developmentRebuild.js} +1 -1
  203. package/dist/gulp/tasks/{themes.js → BU/themes.js} +3 -2
  204. package/dist/gulp/tasks/{test.js → _.js} +3 -3
  205. package/dist/gulp/tasks/audit.js +154 -0
  206. package/dist/gulp/tasks/defaults.js +308 -0
  207. package/dist/gulp/tasks/distribute.js +87 -92
  208. package/dist/gulp/tasks/html.js +150 -0
  209. package/dist/gulp/tasks/icons.js +3 -2
  210. package/dist/gulp/tasks/package.js +216 -27
  211. package/dist/gulp/tasks/sass.js +188 -43
  212. package/dist/gulp/tasks/serve.js +1 -0
  213. package/dist/gulp/tasks/utils/template-transform.js +50 -0
  214. package/dist/gulp/tasks/webpack.js +338 -134
  215. package/dist/index.js +34 -34
  216. package/dist/options.js +40 -0
  217. package/dist/page.js +40 -0
  218. package/dist/popup.js +40 -0
  219. package/dist/sidepanel.js +40 -0
  220. package/firebase-debug.log +322 -0
  221. package/package.json +25 -18
  222. package/dist/assets/css/main.scss +0 -3
  223. package/dist/assets/themes/bootstrap/5.3.3/css/bootstrap.css +0 -12057
  224. package/dist/assets/themes/bootstrap/5.3.3/css/bootstrap.css.map +0 -1
  225. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.bundle.js +0 -6314
  226. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.bundle.js.map +0 -1
  227. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.js +0 -4494
  228. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.js.map +0 -1
  229. package/dist/defaults/src/assets/css/content.scss +0 -2
  230. package/dist/defaults/src/assets/css/options.scss +0 -11
  231. package/dist/defaults/src/assets/css/popup.scss +0 -14
  232. package/dist/defaults/src/assets/js/background.js +0 -18
  233. package/dist/defaults/src/assets/js/content.js +0 -15
  234. package/dist/defaults/src/assets/js/options.js +0 -17
  235. package/dist/defaults/src/assets/js/popup.js +0 -17
  236. package/dist/defaults/src/pages/options.html +0 -26
  237. package/dist/defaults/src/pages/popup.html +0 -26
  238. /package/dist/{defaults/src/assets/images/_ → assets/css/bundles/.gitkeep} +0 -0
  239. /package/dist/assets/css/{fontawesome.scss → core/_fontawesome.scss} +0 -0
  240. /package/dist/defaults/src/assets/{vendor/_ → images/.gitkeep} +0 -0
  241. /package/dist/gulp/tasks/{_importer.js → BU/_importer.js} +0 -0
  242. /package/dist/gulp/tasks/{_vendor.js → BU/_vendor.js} +0 -0
@@ -0,0 +1,65 @@
1
+ // Navbar scroll effect for Classy theme
2
+ export default function setupNavbarScroll() {
3
+ const navbar = document.querySelector('.navbar-floating');
4
+ if (!navbar) return;
5
+
6
+ let scrollThreshold = 50; // Pixels to scroll before showing background
7
+ let isGlassy = false;
8
+ let currentOpacity = 0;
9
+ let targetOpacity = 0;
10
+ let animationFrame = null;
11
+
12
+ // Set initial custom property for ::before opacity
13
+ navbar.style.setProperty('--navbar-before-opacity', '0');
14
+
15
+ function animateOpacity() {
16
+ const diff = targetOpacity - currentOpacity;
17
+
18
+ if (Math.abs(diff) > 0.01) {
19
+ currentOpacity += diff * 0.1;
20
+ navbar.style.setProperty('--navbar-before-opacity', currentOpacity);
21
+ animationFrame = requestAnimationFrame(animateOpacity);
22
+ } else {
23
+ currentOpacity = targetOpacity;
24
+ navbar.style.setProperty('--navbar-before-opacity', currentOpacity);
25
+ animationFrame = null;
26
+ }
27
+ }
28
+
29
+ function updateNavbar() {
30
+ const shouldBeGlassy = window.scrollY > scrollThreshold;
31
+
32
+ if (shouldBeGlassy !== isGlassy) {
33
+ isGlassy = shouldBeGlassy;
34
+
35
+ if (isGlassy) {
36
+ navbar.classList.add('bg-glassy', 'shadow-sm');
37
+ targetOpacity = 0.25;
38
+ } else {
39
+ navbar.classList.remove('bg-glassy', 'shadow-sm');
40
+ targetOpacity = 0;
41
+ }
42
+
43
+ if (!animationFrame) {
44
+ animateOpacity();
45
+ }
46
+ }
47
+ }
48
+
49
+ // Initial check
50
+ updateNavbar();
51
+
52
+ // Listen for scroll events with requestAnimationFrame
53
+ let ticking = false;
54
+ function requestTick() {
55
+ if (!ticking) {
56
+ ticking = true;
57
+ window.requestAnimationFrame(() => {
58
+ updateNavbar();
59
+ ticking = false;
60
+ });
61
+ }
62
+ }
63
+
64
+ window.addEventListener('scroll', requestTick, { passive: true });
65
+ }
@@ -1,326 +1,302 @@
1
1
  // Libraries
2
+ import extension from './lib/extension.js';
3
+ import LoggerLite from './lib/logger-lite.js';
2
4
 
3
5
  // Variables
4
6
  const serviceWorker = self;
5
7
 
6
- // Class
7
- function Manager() {
8
- const self = this;
9
-
10
- // Properties
11
- self.extension = null;
12
- self.logger = null;
13
-
14
- // Defaults
15
- self.config = {};
16
- self.version = '%%% version %%%';
17
- self.brand = {
18
- name: '%%% brand.name %%%',
19
- };
20
- self.app = '%%% app.id %%%';
21
- self.environment = '%%% environment %%%';
22
- self.libraries = {
23
- firebase: false,
24
- messaging: false,
25
- promoServer: false,
26
- cachePolyfill: false,
27
- };
28
- self.cache = {
29
- breaker: '',
30
- name: ''
31
- };
32
-
33
- // Return
34
- return self;
35
- }
8
+ // Import build config at the top level (synchronous)
9
+ importScripts('/build.js');
36
10
 
37
- // Initialize
38
- Manager.prototype.initialize = function () {
39
- const self = this;
11
+ // ⚠️⚠️⚠️ CRITICAL: Setup global listeners BEFORE importing Firebase ⚠️⚠️⚠️
12
+ // https://stackoverflow.com/questions/78270541/cant-catch-fcm-notificationclick-event-in-service-worker-using-firebase-messa
13
+ setupGlobalHandlers();
40
14
 
41
- return new Promise(function(resolve, reject) {
15
+ // Import Firebase libraries at the top level (before any async operations)
16
+ // ⚠️ importScripts MUST be called at top-level (synchronously) - it cannot be called inside functions or after async operations
17
+ // importScripts(
18
+ // 'https://www.gstatic.com/firebasejs/%%% firebaseVersion %%%/firebase-app-compat.js',
19
+ // 'https://www.gstatic.com/firebasejs/%%% firebaseVersion %%%/firebase-messaging-compat.js',
20
+ // );
21
+
22
+ // Class
23
+ class Manager {
24
+ constructor() {
42
25
  // Properties
43
- self.extension = require('./lib/extension');
44
- self.logger = new (require('./lib/logger-lite'))('background');
26
+ this.extension = null;
27
+ this.logger = null;
28
+ this.serviceWorker = null;
29
+
30
+ // Load config from build.js
31
+ this.config = serviceWorker.BEM_BUILD_JSON?.config || {};
32
+
33
+ // Defaults
34
+ this.version = this.config?.version || 'unknown';
35
+ this.brand = this.config?.brand || { name: 'unknown' };
36
+ this.app = this.config?.app?.id || 'extension';
37
+ this.environment = this.config?.bem?.environment || 'production';
38
+ this.libraries = {
39
+ firebase: false,
40
+ messaging: false,
41
+ promoServer: false,
42
+ };
43
+ this.cache = {
44
+ breaker: this.config?.bem?.cache_breaker || new Date().getTime(),
45
+ name: ''
46
+ };
47
+ }
48
+
49
+ // Initialize
50
+ async initialize() {
51
+ // Set properties
52
+ this.extension = extension;
53
+ this.logger = new LoggerLite('background');
54
+ this.serviceWorker = serviceWorker;
45
55
 
46
56
  // Parse config file
47
- parseConfiguration(self);
57
+ this.parseConfiguration();
48
58
 
49
- // Setup listeners
50
- setupListeners(self);
59
+ // Setup instance-specific message handlers
60
+ this.setupInstanceHandlers();
51
61
 
52
- // Import firebase
53
- // importFirebase(self);
62
+ // Initialize Firebase
63
+ this.initializeFirebase();
54
64
 
55
65
  // Setup livereload
56
- setupLiveReload(self);
66
+ this.setupLiveReload();
57
67
 
58
68
  // Log
59
- self.logger.log('Initialized!', self.version, self.cache.name, self);
60
-
61
- // Return
62
- return resolve(self);
63
- });
64
- };
69
+ this.logger.log('Initialized!', this.version, this.cache.name, this);
70
+ this.logger.log('Config loaded from BEM_BUILD_JSON:', this.config);
65
71
 
66
- // Parse configuration
67
- function parseConfiguration(self) {
68
- try {
69
- // Log
70
- self.cache.breaker = new Date().getTime();
71
- self.cache.name = `${self.app}-${self.cache.breaker}`;
72
-
73
- self.logger.log('Parsed configuration', self.config);
74
- } catch (e) {
75
- self.logger.error('Error parsing configuration', e);
72
+ // Return manager instance
73
+ return this;
76
74
  }
77
- }
78
-
79
- // Setup listeners
80
- function setupListeners(self) {
81
- // Force service worker to use the latest version
82
- serviceWorker.addEventListener('install', (event) => {
83
- event.waitUntil(serviceWorker.skipWaiting());
84
- });
85
-
86
- serviceWorker.addEventListener('activate', (event) => {
87
- event.waitUntil(serviceWorker.clients.claim());
88
- });
89
-
90
- // Handle clicks on notifications
91
- // Open the URL of the notification
92
- // ⚠️⚠️⚠️ THIS MUST BE PLACED BEFORE THE FIREBASE IMPORTS HANDLER ⚠️⚠️⚠️
93
- // https://stackoverflow.com/questions/78270541/cant-catch-fcm-notificationclick-event-in-background-using-firebase-messa
94
- serviceWorker.addEventListener('notificationclick', (event) => {
95
- // Get the properties of the notification
96
- const notification = event.notification;
97
- const data = (notification.data && notification.data.FCM_MSG ? notification.data.FCM_MSG.data : null) || {};
98
- const payload = (notification.data && notification.data.FCM_MSG ? notification.data.FCM_MSG.notification : null) || {};
99
75
 
100
- // Get the click action
101
- const clickAction = payload.click_action || data.click_action || '/';
102
-
103
- // Log
104
- self.logger.log('Event: notificationclick event', event);
105
- self.logger.log('Event: notificationclick data', data);
106
- self.logger.log('Event: notificationclick payload', payload);
107
- self.logger.log('Event: notificationclick clickAction', clickAction);
108
-
109
- // Handle the click
110
- event.waitUntil(
111
- clients.openWindow(clickAction)
112
- );
76
+ // Parse configuration
77
+ parseConfiguration() {
78
+ try {
79
+ // Set cache name
80
+ this.cache.name = `${this.app}-${this.cache.breaker}`;
113
81
 
114
- // Close the notification
115
- notification.close();
116
- });
82
+ this.logger.log('Parsed configuration', this.config);
83
+ } catch (e) {
84
+ this.logger.error('Error parsing configuration', e);
85
+ }
86
+ }
117
87
 
118
- // Send messages: https://stackoverflow.com/questions/35725594/how-do-i-pass-data-like-a-user-id-to-a-web-worker-for-fetching-additional-push
119
- // more messaging: http://craig-russell.co.uk/2016/01/29/background-messaging.html#.XSKpRZNKiL8
120
- serviceWorker.addEventListener('message', (event) => {
121
- try {
88
+ // Setup instance-specific message handlers
89
+ setupInstanceHandlers() {
90
+ // Send messages: https://stackoverflow.com/questions/35725594/how-do-i-pass-data-like-a-user-id-to-a-web-worker-for-fetching-additional-push
91
+ // more messaging: http://craig-russell.co.uk/2016/01/29/background-messaging.html#.XSKpRZNKiL8
92
+ serviceWorker.addEventListener('message', (event) => {
122
93
  // Get the data
123
94
  const data = event.data || {};
124
- const response = {
125
- status: 'success',
126
- command: '',
127
- data: {}
128
- };
129
95
 
130
96
  // Parse the data
131
- data.command = data.command || '';
132
- data.args = data.args || {};
133
- response.command = data.command;
97
+ const command = data.command || '';
98
+ const payload = data.payload || {};
134
99
 
135
100
  // Quit if no command
136
- if (data.command === '') { return };
101
+ if (!command) return;
137
102
 
138
103
  // Log
139
- self.logger.log('Event: postMessage', data);
140
-
141
- // Handle the command
142
- if (data.command === 'function') {
143
- data.args.function = data.args.function || function() {};
144
- data.args.function();
145
- } else if (data.command === 'debug') {
146
- self.logger.log('Debug data =', data);
147
- event.ports[0].postMessage(response);
148
- } else if (data.command === 'skipWaiting') {
149
- self.skipWaiting();
150
- event.ports[0].postMessage(response);
151
- } else if (data.command === 'unregister') {
152
- self.registration.unregister()
153
- .then(() => {
154
- event.ports[0].postMessage(response);
155
- })
156
- .catch(() => {
157
- response.status = 'fail';
158
- event.ports[0].postMessage(response);
159
- });
160
- } else if (data.command === 'cache') {
161
- data.args.pages = data.args.pages || [];
162
- var defaultPages =
163
- [
164
- '/',
165
- '/index.html',
166
- /* '/?homescreen=1', */
167
- '/assets/css/main.css',
168
- '/assets/js/main.js',
169
- ];
170
- var pagesToCache = arrayUnique(data.args.pages.concat(defaultPages));
171
- caches.open(SWManager.cache.name).then(cache => {
172
- return cache.addAll(
173
- pagesToCache
174
- )
104
+ this.logger.log('message', command, payload, event);
105
+
106
+ // Handle commands
107
+ if (command === 'update-cache') {
108
+ const pages = payload.pages || [];
109
+ this.updateCache(pages)
175
110
  .then(() => {
176
- self.logger.log('Cached resources.');
177
- event.ports[0].postMessage(response);
111
+ event.ports[0]?.postMessage({ status: 'success' });
178
112
  })
179
- .catch(() => {
180
- response.status = 'fail';
181
- event.ports[0].postMessage(response);
182
- self.logger.log('Failed to cache resources.')
113
+ .catch(error => {
114
+ event.ports[0]?.postMessage({ status: 'error', error: error.message });
183
115
  });
184
- })
185
116
  }
117
+ });
186
118
 
187
- event.ports[0].postMessage(response);
188
- } catch (e) {
189
- // Set up a response
190
- response.success = 'fail';
119
+ // Log
120
+ this.logger.log('Set up message handlers');
121
+ }
191
122
 
192
- // Try to send a response
193
- try { event.ports[0].postMessage(response) } catch (e) {}
123
+ // Initialize Firebase
124
+ initializeFirebase() {
125
+ // Get Firebase config
126
+ const firebaseConfig = this.config?.web_manager?.firebase?.app?.config;
194
127
 
195
- // Log
196
- self.logger.log('Failed to receive message:', data, e);
128
+ // Check if Firebase config is available
129
+ if (!firebaseConfig) {
130
+ this.logger.log('Firebase config not available yet, skipping Firebase initialization');
131
+ return;
197
132
  }
198
- });
199
133
 
200
- // Log
201
- self.logger.log('Set up listeners');
202
- }
134
+ // Check if already initialized
135
+ if (this.libraries.firebase) {
136
+ this.logger.log('Firebase already initialized');
137
+ return;
138
+ }
203
139
 
204
- // Import Firebase
205
- function importFirebase(self) {
206
- // Import Firebase libraries
207
- // importScripts(
208
- // 'https://www.gstatic.com/firebasejs/%%% firebaseVersion %%%/firebase-app-compat.js',
209
- // 'https://www.gstatic.com/firebasejs/%%% firebaseVersion %%%/firebase-messaging-compat.js',
210
- // 'https://www.gstatic.com/firebasejs/%%% firebaseVersion %%%/firebase-database-compat.js',
211
- // 'https://www.gstatic.com/firebasejs/%%% firebaseVersion %%%/firebase-firestore-compat.js',
212
- // );
213
- console.error('---0');
214
- console.error('---1', __dirname);
215
- // const firebase = require('web-manager/node_modules/firebase/firebase-app-compat.js');
216
- // const firebase = require('web-manager');
217
- // const firebase = require('firebase/firebase-auth-compat.js');
218
- console.error('---2', firebase);
219
-
220
- // Initialize app
221
- const app = firebase.initializeApp(self.config.firebase);
222
-
223
- // Initialize messaging
224
- self.libraries.messaging = firebase.messaging();
225
-
226
- // Attach firebase to SWManager
227
- self.libraries.firebase = firebase;
228
- }
140
+ // Log
141
+ this.logger.log('Initializing Firebase');
229
142
 
230
- function setupLiveReload(self) {
231
- // Quit if not in dev mode
232
- if (self.environment !== 'development') { return };
143
+ // Initialize app (libraries were already imported at the top if uncommented)
144
+ // firebase.initializeApp(firebaseConfig);
145
+
146
+ // Initialize messaging
147
+ // this.libraries.messaging = firebase.messaging();
148
+
149
+ // Attach firebase to Manager
150
+ // this.libraries.firebase = firebase;
151
+ }
152
+
153
+ // Update cache
154
+ updateCache(pages) {
155
+ // Set default pages to cache
156
+ const defaults = [
157
+ '/',
158
+ '/assets/css/main.bundle.css',
159
+ '/assets/js/main.bundle.js',
160
+ ];
161
+
162
+ // Ensure pages is an array
163
+ pages = pages || [];
164
+
165
+ // Merge with additional pages
166
+ const pagesToCache = [...new Set([...defaults, ...pages])];
167
+
168
+ // Open cache and add pages
169
+ return caches.open(this.cache.name)
170
+ .then(cache => cache.addAll(pagesToCache))
171
+ .then(() => this.logger.log('Cached resources:', pagesToCache))
172
+ .catch(error => this.logger.error('Failed to cache resources:', error));
173
+ }
233
174
 
234
175
  // Setup livereload
235
- const address = `ws://localhost:%%% liveReloadPort %%%/livereload`;
236
- let connection;
237
- let isReconnecting = false; // Flag to track reconnections
176
+ setupLiveReload() {
177
+ // Quit if not in dev mode
178
+ if (this.environment !== 'development') return;
238
179
 
239
- // Function to establish a connection
240
- function connect() {
241
- connection = new WebSocket(address);
180
+ // Get port from config or use default
181
+ const port = this.config?.bem?.liveReloadPort || 35729;
242
182
 
243
- // Log connection
244
- self.logger.log(`Reload connecting to ${address}...`);
183
+ // Setup livereload
184
+ const address = `ws://localhost:${port}/livereload`;
185
+ let connection;
186
+ let isReconnecting = false; // Flag to track reconnections
245
187
 
246
- // Log connection errors
247
- connection.onerror = (e) => {
248
- self.logger.error('Reload connection got error:', e);
249
- };
188
+ // Log
189
+ this.logger.log(`Setting up live reload on ${address}...`);
250
190
 
251
- // Log when set up correctly
252
- connection.onopen = () => {
253
- self.logger.log('Reload connection set up!');
191
+ // Function to establish a connection
192
+ const connect = () => {
193
+ connection = new WebSocket(address);
254
194
 
255
- // Reload the extension only on reconnections
256
- if (isReconnecting) {
257
- // reload();
258
- }
195
+ // Log connection
196
+ this.logger.log(`Reload connecting to ${address}...`);
259
197
 
260
- // Reset the reconnection flag
261
- isReconnecting = false;
262
- };
198
+ // Log connection errors
199
+ connection.onerror = (e) => {
200
+ this.logger.error('Reload connection got error:', e);
201
+ };
263
202
 
264
- // Handle connection close and attempt to reconnect
265
- connection.onclose = () => {
266
- // Set time
267
- const seconds = 1;
203
+ // Log when set up correctly
204
+ connection.onopen = () => {
205
+ this.logger.log('Reload connection set up!');
268
206
 
269
- // Log
270
- self.logger.log(`Reload connection closed. Attempting to reconnect in ${seconds} second(s)...`);
207
+ // Reload the extension only on reconnections
208
+ if (isReconnecting) {
209
+ // reload();
210
+ }
271
211
 
272
- // Set the reconnection flag
273
- isReconnecting = true;
212
+ // Reset the reconnection flag
213
+ isReconnecting = false;
214
+ };
274
215
 
275
- // Reconnect
276
- setTimeout(connect, seconds * 1000); // Retry
277
- };
216
+ // Handle connection close and attempt to reconnect
217
+ connection.onclose = () => {
218
+ // Set time
219
+ const seconds = 1;
278
220
 
279
- // Handle incoming messages
280
- connection.onmessage = function (event) {
281
- if (!event.data) {
282
- return;
283
- }
221
+ // Log
222
+ this.logger.log(`Reload connection closed. Attempting to reconnect in ${seconds} second(s)...`);
284
223
 
285
- // Get data
286
- const data = JSON.parse(event.data);
224
+ // Set the reconnection flag
225
+ isReconnecting = true;
287
226
 
288
- // Log
289
- self.logger.log('Reload connection got message:', data);
227
+ // Reconnect
228
+ setTimeout(connect, seconds * 1000); // Retry
229
+ };
290
230
 
291
- // Handle reload command
292
- if (data && data.command === 'reload') {
293
- reload();
294
- }
231
+ // Handle incoming messages
232
+ connection.onmessage = (event) => {
233
+ if (!event.data) {
234
+ return;
235
+ }
236
+
237
+ // Get data
238
+ const data = JSON.parse(event.data);
239
+
240
+ // Log
241
+ this.logger.log('Reload connection got message:', data);
242
+
243
+ // Handle reload command
244
+ if (data && data.command === 'reload') {
245
+ reload();
246
+ }
247
+ };
295
248
  };
296
- }
297
249
 
298
- function reload() {
299
- self.logger.log('Reloading extension...');
300
- setTimeout(() => {
301
- self.extension.runtime.reload();
302
- }, 1000);
303
- }
250
+ const reload = () => {
251
+ this.logger.log('Reloading extension...');
252
+ setTimeout(() => {
253
+ this.extension.runtime.reload();
254
+ }, 1000);
255
+ };
304
256
 
305
- // Start the initial connection
306
- connect();
257
+ // Start the initial connection
258
+ connect();
259
+ }
307
260
  }
308
261
 
309
- function arrayUnique(array) {
310
- var a = array.concat();
262
+ // Helper: Setup global listeners
263
+ // This is called at top-level before any async operations to ensure listeners are registered first
264
+ function setupGlobalHandlers() {
265
+ // Force service worker to use the latest version
266
+ serviceWorker.addEventListener('install', (event) => {
267
+ serviceWorker.skipWaiting();
268
+ });
311
269
 
312
- // Loop through array
313
- for(var i=0; i<a.length; ++i) {
314
- for(var j=i+1; j<a.length; ++j) {
315
- if(a[i] === a[j]) {
316
- a.splice(j--, 1);
317
- }
318
- }
319
- }
270
+ serviceWorker.addEventListener('activate', (event) => {
271
+ event.waitUntil(serviceWorker.clients.claim());
272
+ });
273
+
274
+ // Handle clicks on notifications
275
+ // ⚠️ MUST be registered before any async operations
276
+ serviceWorker.addEventListener('notificationclick', (event) => {
277
+ // Get the properties of the notification
278
+ const notification = event.notification;
279
+ const data = (notification.data && notification.data.FCM_MSG ? notification.data.FCM_MSG.data : null) || {};
280
+ const payload = (notification.data && notification.data.FCM_MSG ? notification.data.FCM_MSG.notification : null) || {};
320
281
 
321
- // Return
322
- return a;
282
+ // Get the click action
283
+ const clickAction = payload.click_action || data.click_action || '/';
284
+
285
+ // Log
286
+ console.log('notificationclick event', event);
287
+ console.log('notificationclick data', data);
288
+ console.log('notificationclick payload', payload);
289
+ console.log('notificationclick clickAction', clickAction);
290
+
291
+ // Handle the click
292
+ event.waitUntil(
293
+ clients.openWindow(clickAction)
294
+ );
295
+
296
+ // Close the notification
297
+ notification.close();
298
+ });
323
299
  }
324
300
 
325
301
  // Export
326
- module.exports = Manager;
302
+ export default Manager;