Odoo18-Base/addons/web_unsplash/static/src/unsplash_service.js
2025-01-06 10:57:38 +07:00

131 lines
5.4 KiB
JavaScript

import { rpc } from "@web/core/network/rpc";
import { registry } from "@web/core/registry";
import { _t } from "@web/core/l10n/translation";
import { AUTOCLOSE_DELAY } from "@html_editor/main/media/media_dialog/upload_progress_toast/upload_service";
export const unsplashService = {
dependencies: ["upload"],
async start(env, { upload }) {
const _cache = {};
return {
async uploadUnsplashRecords(records, { resModel, resId }, onUploaded) {
upload.incrementId();
const file = upload.addFile({
id: upload.fileId,
name:
records.length > 1
? _t("Uploading %(count)s '%(query)s' images.", {
count: records.length,
query: records[0].query,
})
: _t("Uploading '%s' image.", records[0].query),
});
try {
const urls = {};
for (const record of records) {
const _1920Url = new URL(record.urls.regular);
_1920Url.searchParams.set("w", "1920");
urls[record.id] = {
url: _1920Url.href,
download_url: record.links.download_location,
description: record.alt_description,
};
}
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (ev) => {
const rpcComplete = (ev.loaded / ev.total) * 100;
file.progress = rpcComplete;
});
xhr.upload.addEventListener("load", function () {
// Don't show yet success as backend code only starts now
file.progress = 100;
});
const attachments = await rpc(
"/web_unsplash/attachment/add",
{
res_id: resId,
res_model: resModel,
unsplashurls: urls,
query: records[0].query,
},
{ xhr }
);
if (attachments.error) {
file.hasError = true;
file.errorMessage = attachments.error;
} else {
file.uploaded = true;
await onUploaded(attachments);
}
setTimeout(() => upload.deleteFile(file.id), AUTOCLOSE_DELAY);
} catch (error) {
file.hasError = true;
setTimeout(() => upload.deleteFile(file.id), AUTOCLOSE_DELAY);
throw error;
}
},
async getImages(query, offset = 0, pageSize = 30, orientation) {
const from = offset;
const to = offset + pageSize;
// Use orientation in the cache key to not show images in cache
// when using the same query word but changing the orientation
let cachedData = orientation ? _cache[query + orientation] : _cache[query];
if (
cachedData &&
(cachedData.images.length >= to ||
(cachedData.totalImages !== 0 && cachedData.totalImages < to))
) {
return {
images: cachedData.images.slice(from, to),
isMaxed: to > cachedData.totalImages,
};
}
cachedData = await this._fetchImages(query, orientation);
return {
images: cachedData.images.slice(from, to),
isMaxed: to > cachedData.totalImages,
};
},
/**
* Fetches images from unsplash and stores it in cache
*/
async _fetchImages(query, orientation) {
const key = orientation ? query + orientation : query;
if (!_cache[key]) {
_cache[key] = {
images: [],
maxPages: 0,
totalImages: 0,
pageCached: 0,
};
}
const cachedData = _cache[key];
const payload = {
query: query,
page: cachedData.pageCached + 1,
per_page: 30, // max size from unsplash API
};
if (orientation) {
payload.orientation = orientation;
}
const result = await rpc("/web_unsplash/fetch_images", payload);
if (result.error) {
return Promise.reject(result.error);
}
cachedData.pageCached++;
cachedData.images.push(...result.results);
cachedData.maxPages = result.total_pages;
cachedData.totalImages = result.total;
return cachedData;
},
};
},
};
registry.category("services").add("unsplash", unsplashService);