Skip to content

Commit f3dfec0

Browse files
committed
refactor: image progress
1 parent fd9a487 commit f3dfec0

File tree

2 files changed

+150
-117
lines changed

2 files changed

+150
-117
lines changed

js/app/guest/guest.js

+28-117
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { image } from './image.js';
12
import { audio } from './audio.js';
23
import { progress } from './progress.js';
34
import { util } from '../../common/util.js';
@@ -83,7 +84,8 @@ export const guest = (() => {
8384
div.classList.add('m-2');
8485
div.innerHTML = `
8586
<p class="mt-0 mb-1 mx-0 p-0" style="font-size: 0.95rem;">${guest?.getAttribute('data-message')}</p>
86-
<h2 class="m-0 p-0">${util.escapeHtml(name)}</h2>`;
87+
<h2 class="m-0 p-0">${util.escapeHtml(name)}</h2>
88+
`;
8789

8890
guest?.appendChild(div);
8991
}
@@ -147,96 +149,12 @@ export const guest = (() => {
147149
/**
148150
* @returns {void}
149151
*/
150-
const normalize = () => {
152+
const normalizeArabicFont = () => {
151153
document.querySelectorAll('.font-arabic').forEach((el) => {
152154
el.innerHTML = String(el.innerHTML).normalize('NFC');
153155
});
154156
};
155157

156-
/**
157-
* @returns {void}
158-
*/
159-
const imageProgress = () => {
160-
/**
161-
* @type {Map<string, string>}
162-
*/
163-
const uniqueUrl = new Map();
164-
165-
/**
166-
* @param {HTMLImageElement} el
167-
* @returns {Promise<void>}
168-
*/
169-
const getByFetch = async (el) => {
170-
// 6 hour TTL
171-
const ttl = 1000 * 60 * 60 * 6;
172-
const url = el.getAttribute('data-src');
173-
const exp = 'x-expiration-time';
174-
const cacheName = 'image_cache';
175-
176-
if (uniqueUrl.has(url)) {
177-
el.src = uniqueUrl.get(url);
178-
progress.complete('image');
179-
return;
180-
}
181-
182-
/**
183-
* @param {Cache} c
184-
* @returns {Promise<blob>}
185-
*/
186-
const fetchPut = (c) => {
187-
return fetch(url).then((res) => res.blob().then((b) => {
188-
const headers = new Headers(res.headers);
189-
headers.append(exp, String(Date.now() + ttl));
190-
191-
return c.put(url, new Response(b, { headers })).then(() => b);
192-
}));
193-
};
194-
195-
await caches.open(cacheName).then((c) => {
196-
return c.match(url).then((res) => {
197-
if (!res) {
198-
return fetchPut(c);
199-
}
200-
201-
if (Date.now() <= parseInt(res.headers.get(exp))) {
202-
return res.blob();
203-
}
204-
205-
return c.delete(url).then((s) => s ? fetchPut(c) : res.blob());
206-
}).then((b) => {
207-
el.src = URL.createObjectURL(b);
208-
uniqueUrl.set(url, el.src);
209-
progress.complete('image');
210-
})
211-
}).catch(() => progress.invalid('image'));
212-
};
213-
214-
/**
215-
* @param {HTMLImageElement} el
216-
* @returns {void}
217-
*/
218-
const getByDefault = (el) => {
219-
el.onerror = () => progress.invalid('image');
220-
el.onload = () => progress.complete('image');
221-
222-
if (el.complete && el.naturalWidth !== 0 && el.naturalHeight !== 0) {
223-
progress.complete('image');
224-
} else if (el.complete) {
225-
progress.invalid('image');
226-
}
227-
};
228-
229-
(async (els) => {
230-
for (const el of els) {
231-
if (el.hasAttribute('data-src')) {
232-
await getByFetch(el);
233-
} else {
234-
getByDefault(el);
235-
}
236-
}
237-
})(document.querySelectorAll('img'));
238-
};
239-
240158
/**
241159
* @returns {object}
242160
*/
@@ -246,13 +164,12 @@ export const guest = (() => {
246164
offline.init();
247165
progress.init();
248166

249-
normalize();
250167
countDownDate();
168+
normalizeArabicFont();
251169
information = storage('information');
252-
document.addEventListener('progressDone', () => {
253-
showGuestName();
254-
window.AOS.init();
255-
});
170+
171+
document.addEventListener('progressDone', showGuestName);
172+
document.addEventListener('progressDone', window.AOS.init);
256173

257174
if (session.isAdmin()) {
258175
storage('user').clear();
@@ -272,12 +189,9 @@ export const guest = (() => {
272189
info.remove();
273190
}
274191

275-
// add total image.
276-
document.querySelectorAll('img').forEach(progress.add);
277-
278192
const token = document.body.getAttribute('data-key');
279193
if (!token || token.length === 0) {
280-
imageProgress();
194+
image.init().load();
281195
document.getElementById('comment')?.remove();
282196
document.querySelector('a.nav-link[href="#comment"]')?.closest('li.nav-item')?.remove();
283197
}
@@ -287,31 +201,28 @@ export const guest = (() => {
287201
progress.add();
288202
progress.add();
289203

290-
const hasDataSrc = Array.from(document.querySelectorAll('img')).some((i) => i.hasAttribute('data-src'));
291-
if (!hasDataSrc) {
292-
imageProgress();
204+
const img = image.init();
205+
if (!img.hasDataSrc()) {
206+
img.load();
293207
}
294208

295209
session.setToken(token);
296-
session.guest()
297-
.then((res) => {
298-
if (res.code !== 200) {
299-
progress.invalid('config');
300-
return;
301-
}
302-
303-
progress.complete('config');
304-
305-
if (hasDataSrc) {
306-
imageProgress();
307-
}
308-
309-
comment.init();
310-
comment.comment()
311-
.then(() => progress.complete('comment'))
312-
.catch(() => progress.invalid('comment'));
313-
})
314-
.catch(() => progress.invalid('config'));
210+
session.guest().then((res) => {
211+
if (res.code !== 200) {
212+
progress.invalid('config');
213+
return;
214+
}
215+
216+
progress.complete('config');
217+
if (img.hasDataSrc()) {
218+
img.load();
219+
}
220+
221+
comment.init();
222+
comment.comment()
223+
.then(() => progress.complete('comment'))
224+
.catch(() => progress.invalid('comment'));
225+
}).catch(() => progress.invalid('config'));
315226
}
316227

317228
return {

js/app/guest/image.js

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { progress } from './progress.js';
2+
3+
export const image = (() => {
4+
5+
/**
6+
* @type {Map<string, string>}
7+
*/
8+
let uniqueUrl = null;
9+
10+
/**
11+
* @type {NodeListOf<HTMLImageElement>}
12+
*/
13+
let images = null;
14+
15+
let hasSrc = true;
16+
17+
// 6 hour TTL
18+
const ttl = 1000 * 60 * 60 * 6;
19+
20+
const cacheName = 'image_cache';
21+
22+
/**
23+
* @param {HTMLImageElement} el
24+
* @returns {Promise<void>}
25+
*/
26+
const getByFetch = async (el) => {
27+
const url = el.getAttribute('data-src');
28+
const exp = 'x-expiration-time';
29+
30+
if (uniqueUrl.has(url)) {
31+
el.src = uniqueUrl.get(url);
32+
progress.complete('image');
33+
return;
34+
}
35+
36+
/**
37+
* @param {Cache} c
38+
* @returns {Promise<blob>}
39+
*/
40+
const fetchPut = (c) => {
41+
return fetch(url).then((res) => res.blob().then((b) => {
42+
const headers = new Headers(res.headers);
43+
headers.append(exp, String(Date.now() + ttl));
44+
45+
return c.put(url, new Response(b, { headers })).then(() => b);
46+
}));
47+
};
48+
49+
await caches.open(cacheName).then((c) => {
50+
return c.match(url).then((res) => {
51+
if (!res) {
52+
return fetchPut(c);
53+
}
54+
55+
if (Date.now() <= parseInt(res.headers.get(exp))) {
56+
return res.blob();
57+
}
58+
59+
return c.delete(url).then((s) => s ? fetchPut(c) : res.blob());
60+
}).then((b) => {
61+
el.src = URL.createObjectURL(b);
62+
uniqueUrl.set(url, el.src);
63+
progress.complete('image');
64+
})
65+
}).catch(() => progress.invalid('image'));
66+
};
67+
68+
/**
69+
* @param {HTMLImageElement} el
70+
* @returns {void}
71+
*/
72+
const getByDefault = (el) => {
73+
el.onerror = () => progress.invalid('image');
74+
el.onload = () => progress.complete('image');
75+
76+
if (el.complete && el.naturalWidth !== 0 && el.naturalHeight !== 0) {
77+
progress.complete('image');
78+
} else if (el.complete) {
79+
progress.invalid('image');
80+
}
81+
};
82+
83+
/**
84+
* @returns {boolean}
85+
*/
86+
const hasDataSrc = () => hasSrc;
87+
88+
/**
89+
* @returns {void}
90+
*/
91+
const load = () => {
92+
(async () => {
93+
for (const el of images) {
94+
if (el.hasAttribute('data-src')) {
95+
await getByFetch(el);
96+
} else {
97+
getByDefault(el);
98+
}
99+
}
100+
})();
101+
};
102+
103+
/**
104+
* @returns {object}
105+
*/
106+
const init = () => {
107+
uniqueUrl = new Map();
108+
images = document.querySelectorAll('img');
109+
110+
images.forEach(progress.add);
111+
hasSrc = Array.from(images).some((i) => i.hasAttribute('data-src'));
112+
113+
return {
114+
load,
115+
hasDataSrc,
116+
};
117+
};
118+
119+
return {
120+
init,
121+
};
122+
})();

0 commit comments

Comments
 (0)