@cocreate/pwa 1.13.7 → 1.15.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ # [1.15.0](https://github.com/CoCreate-app/CoCreate-pwa/compare/v1.14.0...v1.15.0) (2023-11-12)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * bump dependencies for latest features ([f786f81](https://github.com/CoCreate-app/CoCreate-pwa/commit/f786f812e921d612b932ddaa7b8d3088ac98a410))
7
+ * relocated persit function out of init ([7725508](https://github.com/CoCreate-app/CoCreate-pwa/commit/7725508a023ece5b231387556849893b845ece73))
8
+
9
+
10
+ ### Features
11
+
12
+ * observe actions=install ([d1f7aea](https://github.com/CoCreate-app/CoCreate-pwa/commit/d1f7aeae233cc8c3d531f66f982ef47e56280d92))
13
+
14
+ # [1.14.0](https://github.com/CoCreate-app/CoCreate-pwa/compare/v1.13.7...v1.14.0) (2023-11-09)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * meta name typo ([3c58a5e](https://github.com/CoCreate-app/CoCreate-pwa/commit/3c58a5ead6d509fb6cf63e57c0c3bc58e21a1e1d))
20
+ * update crud methods ([1b5236c](https://github.com/CoCreate-app/CoCreate-pwa/commit/1b5236c3c91610d9420f96584fbd195eb9c90078))
21
+
22
+
23
+ ### Features
24
+
25
+ * debounce an array of files served from cache and send to client ([4daa134](https://github.com/CoCreate-app/CoCreate-pwa/commit/4daa1344a06049667c22fa6dab8aa229678d726e))
26
+
1
27
  ## [1.13.7](https://github.com/CoCreate-app/CoCreate-pwa/compare/v1.13.6...v1.13.7) (2023-11-03)
2
28
 
3
29
 
package/demo/index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta charset="utf-8" />
6
6
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
7
  <meta
8
- key="viewport"
8
+ name="viewport"
9
9
  content="width=device-width; initial-scale=1; viewport-fit=cover" />
10
10
  <!-- import the webpage's stylesheet -->
11
11
  <link
@@ -23,7 +23,7 @@
23
23
  <meta name="apple-mobile-web-app-capable" content="yes" />
24
24
  <!--<hides status bar for a full screen experience omn ios only>-->
25
25
  <meta
26
- key="apple-mobile-web-app-status-bar-style"
26
+ name="apple-mobile-web-app-status-bar-style"
27
27
  content="black-translucent" />
28
28
 
29
29
  <link rel="apple-touch-startup-image" href="ios-startup.png" />
package/docs/index.html CHANGED
@@ -11,10 +11,10 @@
11
11
  sizes="32x32"
12
12
  href="https://cocreate.app/images/favicon.ico" />
13
13
  <meta
14
- key="description"
14
+ name="description"
15
15
  content="A simple HTML5 and pure javascript component. Easy configuration using data-attributes and highly styleable." />
16
16
  <meta
17
- key="keywords"
17
+ name="keywords"
18
18
  content="helper classes, utility classes, css framework, css library, inline style classes" />
19
19
  <meta name="robots" content="index,follow" />
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/pwa",
3
- "version": "1.13.7",
3
+ "version": "1.15.0",
4
4
  "description": "A simple pwa component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "pwa",
@@ -59,6 +59,6 @@
59
59
  "webpack-log": "^3.0.1"
60
60
  },
61
61
  "dependencies": {
62
- "@cocreate/local-storage": "^1.10.8"
62
+ "@cocreate/local-storage": "^1.10.10"
63
63
  }
64
64
  }
package/src/index.js CHANGED
@@ -15,14 +15,16 @@
15
15
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
  ********************************************************************************/
17
17
 
18
- // Commercial Licensing Information:
19
- // For commercial use of this software without the copyleft provisions of the AGPLv3,
20
- // you must obtain a commercial license from CoCreate LLC.
21
- // For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app.
18
+ /**
19
+ * Commercial Licensing Information:
20
+ * For commercial use of this software without the copyleft provisions of the AGPLv3,
21
+ * you must obtain a commercial license from CoCreate LLC.
22
+ * For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app.
23
+ */
22
24
 
25
+ import observer from '@cocreate/observer'
23
26
  import localStorage from '@cocreate/local-storage'
24
27
 
25
- const button = document.querySelector('[actions*="install"]');
26
28
 
27
29
  /**
28
30
  * Warn the page must be served over HTTPS
@@ -37,41 +39,87 @@ const button = document.querySelector('[actions*="install"]');
37
39
  // requireHTTPS.classList.remove('hidden');
38
40
  // }
39
41
 
40
- window.addEventListener('beforeinstallprompt', (event) => {
41
- // console.log('👍', 'beforeinstallprompt', event);
42
- // Stash the event so it can be triggered later.
43
- window.deferredPrompt = event;
44
- // Remove the 'hidden' class from the install button container
45
- if (button)
46
- button.removeAttribute('hidden');
47
- });
42
+ function init() {
43
+ const button = document.querySelector('[actions*="install"]');
48
44
 
49
- if (button) {
50
- button.addEventListener('click', async () => {
51
- // console.log('👍', 'installBtn-clicked');
52
- const promptEvent = window.deferredPrompt;
53
- if (!promptEvent) {
54
- // The deferred prompt isn't available.
55
- return;
56
- }
57
- // Show the install prompt.
58
- promptEvent.prompt();
59
- // Log the result
60
- const result = await promptEvent.userChoice;
61
- console.log('👍', 'userChoice', result);
62
- // Reset the deferred prompt variable, since
63
- // prompt() can only be called once.
45
+ window.addEventListener('beforeinstallprompt', (event) => {
46
+ window.deferredPrompt = event;
47
+ if (button)
48
+ button.removeAttribute('hidden');
49
+ });
50
+
51
+ if (button) {
52
+ button.addEventListener('click', async () => {
53
+ // console.log('👍', 'installBtn-clicked');
54
+ const promptEvent = window.deferredPrompt;
55
+ if (!promptEvent) {
56
+ // The deferred prompt isn't available.
57
+ return;
58
+ }
59
+ // Show the install prompt.
60
+ promptEvent.prompt();
61
+ // Log the result
62
+ const result = await promptEvent.userChoice;
63
+ console.log('👍', 'userChoice', result);
64
+ // Reset the deferred prompt variable, since
65
+ // prompt() can only be called once.
66
+ window.deferredPrompt = null;
67
+ // Hide the install button.
68
+ button.setAttribute('hidden', '');
69
+ });
70
+ }
71
+
72
+ window.addEventListener('appinstalled', (event) => {
73
+ // console.log('👍', 'appinstalled', event);
74
+ // Clear the deferredPrompt so it can be garbage collected
64
75
  window.deferredPrompt = null;
65
- // Hide the install button.
66
- button.addAttribute('hidden', '');
67
76
  });
68
- }
69
77
 
70
- window.addEventListener('appinstalled', (event) => {
71
- // console.log('👍', 'appinstalled', event);
72
- // Clear the deferredPrompt so it can be garbage collected
73
- window.deferredPrompt = null;
74
- });
78
+ if ('serviceWorker' in navigator) {
79
+ let workerPath
80
+ if (window.CoCreateConfig && window.CoCreateConfig.serviceWorker)
81
+ workerPath = window.CoCreateConfig.serviceWorker
82
+ else
83
+ workerPath = localStorage.getItem("serviceWorker") || '/service-worker.js'
84
+
85
+ localStorage.setItem("serviceWorker", workerPath);
86
+
87
+ let cache
88
+ if (window.CoCreateConfig && window.CoCreateConfig.cache)
89
+ cache = window.CoCreateConfig.cache
90
+ else
91
+ cache = localStorage.getItem("cache") || 'true'
92
+
93
+ localStorage.setItem("cache", cache);
94
+ workerPath += `?cache=${cache}`
95
+
96
+ let isPwa = true
97
+ if (workerPath) {
98
+ navigator.serviceWorker.getRegistrations().then(registrations => {
99
+ if (registrations.length === 0 || isPwa == true)
100
+ window.addEventListener("load", function () {
101
+ navigator.serviceWorker.getRegistration(workerPath).then(registration => {
102
+ if (registration && registration.active && registration.active.scriptURL.includes(workerPath)) {
103
+ console.log('Service Worker Active')
104
+ } else {
105
+ navigator.serviceWorker.register(workerPath)
106
+ .then(reg => {
107
+ reg.onupdatefound = () => {
108
+ const installingWorker = reg.installing;
109
+ installingWorker.onstatechange = () => {
110
+ // console.log('Service Worker', installingWorker.state);
111
+ }
112
+ }
113
+ })
114
+ .catch(err => console.log('SW ERROR', err));
115
+ }
116
+ });
117
+ });
118
+ });
119
+
120
+ }
121
+ }
122
+ }
75
123
 
76
124
  async function persistData() {
77
125
  if (navigator.storage && navigator.storage.persist) {
@@ -80,49 +128,14 @@ async function persistData() {
80
128
  }
81
129
  }
82
130
 
83
- if ('serviceWorker' in navigator) {
84
- let workerPath
85
- if (window.CoCreateConfig && window.CoCreateConfig.serviceWorker)
86
- workerPath = window.CoCreateConfig.serviceWorker
87
- else
88
- workerPath = localStorage.getItem("serviceWorker") || '/service-worker.js'
89
-
90
- localStorage.setItem("serviceWorker", workerPath);
91
-
92
- let cache
93
- if (window.CoCreateConfig && window.CoCreateConfig.cache)
94
- cache = window.CoCreateConfig.cache
95
- else
96
- cache = localStorage.getItem("cache") || 'true'
97
-
98
- localStorage.setItem("cache", cache);
99
- workerPath += `?cache=${cache}`
100
-
101
- let isPwa = true
102
- if (workerPath) {
103
- navigator.serviceWorker.getRegistrations().then(registrations => {
104
- if (registrations.length === 0 || isPwa == true)
105
- window.addEventListener("load", function () {
106
- navigator.serviceWorker.getRegistration(workerPath).then(registration => {
107
- if (registration && registration.active && registration.active.scriptURL.includes(workerPath)) {
108
- console.log('Service Worker Active')
109
- } else {
110
- navigator.serviceWorker.register(workerPath)
111
- .then(reg => {
112
- reg.onupdatefound = () => {
113
- const installingWorker = reg.installing;
114
- installingWorker.onstatechange = () => {
115
- // console.log('Service Worker', installingWorker.state);
116
- }
117
- }
118
- })
119
- .catch(err => console.log('SW ERROR', err));
120
- }
121
- });
122
- });
123
- });
124
-
131
+ observer.init({
132
+ name: 'initPwa',
133
+ observe: ['addedNodes'],
134
+ target: '[actions="install"]',
135
+ callback: (mutation) => {
136
+ init()
125
137
  }
126
- }
138
+ });
139
+
127
140
 
128
141
  export default { persistData }
@@ -25,7 +25,6 @@
25
25
  const cacheName = "dynamic-v2";
26
26
  let organization_id = ""
27
27
  let storage = true
28
- let returnedFromCache = {};
29
28
 
30
29
  const queryString = self.location.search;
31
30
  const queryParams = new URLSearchParams(queryString);
@@ -42,7 +41,7 @@ self.addEventListener("activate", async (e) => {
42
41
 
43
42
  self.addEventListener("fetch", async (e) => {
44
43
  if (!(e.request.url.indexOf('http') === 0) || e.request.method === 'POST') return;
45
- // TODO: check file header for cache policies and cache accorddingly
44
+
46
45
  e.respondWith(
47
46
  caches
48
47
  .match(e.request)
@@ -51,7 +50,8 @@ self.addEventListener("fetch", async (e) => {
51
50
  const organization = cacheResponse.headers.get('organization')
52
51
  const lastModified = cacheResponse.headers.get('last-modified')
53
52
 
54
- returnedFromCache[e.request.url] = { organization, lastModified }
53
+ // returnedFromCache[e.request.url] = { organization, lastModified }
54
+ sendCacheUpdate(e.request.url, organization, lastModified);
55
55
  return cacheResponse;
56
56
  } else {
57
57
  const networkResponse = await fetch(e.request);
@@ -129,7 +129,7 @@ self.addEventListener('push', (event) => {
129
129
  // Handle WebSocket events
130
130
  socket.addEventListener('open', () => {
131
131
  // The WebSocket connection is open, send the message to the server
132
- socket.send(JSON.stringify({ method: 'read.object', array: 'files', object: { _id }, uid: '' }));
132
+ socket.send(JSON.stringify({ method: 'object.read', array: 'files', object: { _id }, uid: '' }));
133
133
  });
134
134
 
135
135
  socket.addEventListener('message', (event) => {
@@ -160,6 +160,28 @@ self.addEventListener('push', (event) => {
160
160
  );
161
161
  });
162
162
 
163
+ let returnedFromCache = {};
164
+ let fetchTimeout = null;
165
+ const sendCacheUpdate = (url, organization, lastModified) => {
166
+
167
+ returnedFromCache[url] = { organization, lastModified };
168
+
169
+ if (fetchTimeout) {
170
+ clearTimeout(fetchTimeout);
171
+ }
172
+ const self = this
173
+ fetchTimeout = setTimeout(() => {
174
+ self.clients.matchAll().then(clients => {
175
+ if (clients.length > 0) {
176
+ clients[0].postMessage({ action: 'checkCache', returnedFromCache });
177
+ }
178
+ });
179
+
180
+ fetchTimeout = null;
181
+ returnedFromCache = {};
182
+ }, 500);
183
+ };
184
+
163
185
  // self.addEventListener('backgroundfetchsuccess', (event) => {
164
186
  // const bgFetch = event.registration;
165
187