2021-12-17 16:25:34 +08:00
|
|
|
import domFromString from "discourse-common/lib/dom-from-string";
|
2019-11-01 00:54:46 +08:00
|
|
|
import {
|
|
|
|
failedCache,
|
2021-10-22 19:15:46 +08:00
|
|
|
lookupCache,
|
2019-11-01 00:54:46 +08:00
|
|
|
normalize,
|
|
|
|
resetFailedCache,
|
|
|
|
resetLocalCache,
|
|
|
|
setFailedCache,
|
|
|
|
setLocalCache,
|
|
|
|
} from "pretty-text/oneboxer-cache";
|
2022-07-17 06:50:49 +08:00
|
|
|
import discourseLater from "discourse-common/lib/later";
|
2019-11-01 00:54:46 +08:00
|
|
|
|
2016-12-20 07:31:10 +08:00
|
|
|
let timeout;
|
|
|
|
const loadingQueue = [];
|
2018-11-27 16:00:31 +08:00
|
|
|
|
|
|
|
export const LOADING_ONEBOX_CSS_CLASS = "loading-onebox";
|
|
|
|
|
|
|
|
export function resetCache() {
|
|
|
|
loadingQueue.clear();
|
2019-11-01 00:54:46 +08:00
|
|
|
resetLocalCache();
|
|
|
|
resetFailedCache();
|
2018-11-27 16:00:31 +08:00
|
|
|
}
|
2016-06-15 02:31:51 +08:00
|
|
|
|
2017-11-13 08:19:06 +08:00
|
|
|
function resolveSize(img) {
|
2021-10-22 19:15:46 +08:00
|
|
|
img.classList.add("size-resolved");
|
2017-11-13 08:19:06 +08:00
|
|
|
|
|
|
|
if (img.width > 0 && img.width === img.height) {
|
2021-10-22 19:15:46 +08:00
|
|
|
img.classList.add("onebox-avatar");
|
2017-11-13 08:19:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Detect square images and apply smaller onebox-avatar class
|
2021-10-22 19:15:46 +08:00
|
|
|
function applySquareGenericOnebox(elem) {
|
|
|
|
if (!elem.classList.contains("allowlistedgeneric")) {
|
2017-11-13 08:19:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-10-22 19:15:46 +08:00
|
|
|
let img = elem.querySelector(".onebox-body img.thumbnail");
|
2017-11-13 08:19:06 +08:00
|
|
|
|
|
|
|
// already resolved... skip
|
2021-10-22 19:15:46 +08:00
|
|
|
if (!img || img.classList.contains("size-resolved")) {
|
2017-11-13 08:19:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (img.complete) {
|
2020-05-07 22:36:15 +08:00
|
|
|
resolveSize(img);
|
2017-11-13 08:19:06 +08:00
|
|
|
} else {
|
2021-10-22 19:15:46 +08:00
|
|
|
img.addEventListener("load", _handleLoadingOneboxImages);
|
2017-11-13 08:19:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-22 19:15:46 +08:00
|
|
|
function _handleLoadingOneboxImages() {
|
|
|
|
resolveSize(this);
|
|
|
|
this.removeEventListener("load", _handleLoadingOneboxImages);
|
|
|
|
}
|
|
|
|
|
2016-12-20 07:31:10 +08:00
|
|
|
function loadNext(ajax) {
|
|
|
|
if (loadingQueue.length === 0) {
|
|
|
|
timeout = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let timeoutMs = 150;
|
|
|
|
let removeLoading = true;
|
2021-10-22 19:15:46 +08:00
|
|
|
const { url, refresh, elem, categoryId, topicId } = loadingQueue.shift();
|
2016-12-20 07:31:10 +08:00
|
|
|
|
|
|
|
// Retrieve the onebox
|
|
|
|
return ajax("/onebox", {
|
|
|
|
dataType: "html",
|
2018-02-20 05:40:14 +08:00
|
|
|
data: {
|
|
|
|
url,
|
|
|
|
refresh,
|
|
|
|
category_id: categoryId,
|
|
|
|
topic_id: topicId,
|
|
|
|
},
|
2016-12-20 07:31:10 +08:00
|
|
|
})
|
|
|
|
.then(
|
2021-12-17 16:25:34 +08:00
|
|
|
(template) => {
|
2022-01-12 19:49:24 +08:00
|
|
|
const node = domFromString(template)[0];
|
2021-10-22 19:15:46 +08:00
|
|
|
setLocalCache(normalize(url), node);
|
|
|
|
elem.replaceWith(node);
|
|
|
|
applySquareGenericOnebox(node);
|
2016-12-20 07:31:10 +08:00
|
|
|
},
|
|
|
|
(result) => {
|
2021-10-22 19:15:46 +08:00
|
|
|
if (result?.jqXHR?.status === 429) {
|
2016-12-20 07:31:10 +08:00
|
|
|
timeoutMs = 2000;
|
|
|
|
removeLoading = false;
|
2021-10-22 19:15:46 +08:00
|
|
|
loadingQueue.unshift({ url, refresh, elem, categoryId, topicId });
|
2016-12-20 07:31:10 +08:00
|
|
|
} else {
|
2019-11-26 13:49:58 +08:00
|
|
|
setFailedCache(normalize(url), true);
|
2016-12-20 07:31:10 +08:00
|
|
|
}
|
|
|
|
}
|
2018-06-15 23:03:24 +08:00
|
|
|
)
|
2016-12-20 07:31:10 +08:00
|
|
|
.finally(() => {
|
2022-07-17 06:50:49 +08:00
|
|
|
timeout = discourseLater(() => loadNext(ajax), timeoutMs);
|
2016-12-20 07:31:10 +08:00
|
|
|
if (removeLoading) {
|
2021-10-22 19:15:46 +08:00
|
|
|
elem.classList.remove(LOADING_ONEBOX_CSS_CLASS);
|
|
|
|
elem.dataset.oneboxLoaded = "";
|
2016-12-20 07:31:10 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-10-22 19:15:46 +08:00
|
|
|
// Perform a lookup of a onebox based an anchor element.
|
2016-10-24 18:46:22 +08:00
|
|
|
// It will insert a loading indicator and remove it when the loading is complete or fails.
|
2018-02-20 05:40:14 +08:00
|
|
|
export function load({
|
|
|
|
elem,
|
|
|
|
ajax,
|
|
|
|
topicId,
|
2021-02-18 22:07:26 +08:00
|
|
|
categoryId,
|
|
|
|
refresh = true,
|
|
|
|
offline = false,
|
|
|
|
synchronous = false,
|
2018-02-20 05:40:14 +08:00
|
|
|
}) {
|
2016-10-24 18:46:22 +08:00
|
|
|
// If the onebox has loaded or is loading, return
|
2021-10-22 19:15:46 +08:00
|
|
|
|
|
|
|
if (elem.dataset.oneboxLoaded) {
|
2020-09-22 22:28:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2021-10-22 19:15:46 +08:00
|
|
|
|
|
|
|
if (elem.classList.contains(LOADING_ONEBOX_CSS_CLASS)) {
|
2020-09-22 22:28:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2016-06-15 02:31:51 +08:00
|
|
|
|
2018-02-14 07:39:44 +08:00
|
|
|
const url = elem.href;
|
2016-06-15 02:31:51 +08:00
|
|
|
|
|
|
|
// Unless we're forcing a refresh...
|
|
|
|
if (!refresh) {
|
|
|
|
// If we have it in our cache, return it.
|
2021-10-22 19:15:46 +08:00
|
|
|
const cached = lookupCache(url);
|
2020-09-22 22:28:28 +08:00
|
|
|
if (cached) {
|
2021-10-22 19:15:46 +08:00
|
|
|
return cached;
|
2020-09-22 22:28:28 +08:00
|
|
|
}
|
2016-06-15 02:31:51 +08:00
|
|
|
|
|
|
|
// If the request failed, don't do anything
|
2017-06-13 00:13:05 +08:00
|
|
|
const failed = failedCache[normalize(url)];
|
2020-09-22 22:28:28 +08:00
|
|
|
if (failed) {
|
|
|
|
return;
|
|
|
|
}
|
2021-02-18 22:07:26 +08:00
|
|
|
|
|
|
|
if (offline) {
|
|
|
|
return;
|
|
|
|
}
|
2016-06-15 02:31:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add the loading CSS class
|
2021-10-22 19:15:46 +08:00
|
|
|
elem.classList.add(LOADING_ONEBOX_CSS_CLASS);
|
2016-06-15 02:31:51 +08:00
|
|
|
|
2016-12-20 07:31:10 +08:00
|
|
|
// Add to the loading queue
|
2021-10-22 19:15:46 +08:00
|
|
|
loadingQueue.push({ url, refresh, elem, categoryId, topicId });
|
2016-12-20 07:31:10 +08:00
|
|
|
|
|
|
|
// Load next url in queue
|
2016-12-20 18:18:03 +08:00
|
|
|
if (synchronous) {
|
2016-12-20 10:26:53 +08:00
|
|
|
return loadNext(ajax);
|
2016-12-20 18:18:03 +08:00
|
|
|
} else {
|
2022-07-17 06:50:49 +08:00
|
|
|
timeout = timeout || discourseLater(() => loadNext(ajax), 150);
|
2016-12-20 10:26:53 +08:00
|
|
|
}
|
2016-06-15 02:31:51 +08:00
|
|
|
}
|