import { UpploadService } from "../service"; import { IHandlersParams, IServiceTemplateParams, IUpploadFile, } from "../helpers/interfaces"; import { cachedFetch, imageUrlToBlob } from "../helpers/http"; import { safeListen } from "../helpers/elements"; import { colorSVG } from "./assets"; import { blobToUpploadFile } from "./files"; let params: any | undefined = undefined; const generateFileName = ( file: IUpploadFile, service: string, query?: string | null ) => { file.name = `${query || `${service}-import`}-${Math.random() .toString(36) .slice(2)}.jpg`; file.type = "image/jpeg"; return file; }; export class SearchBaseClass extends UpploadService { apiKey: string; results: ImageResult[] = []; loading = false; poweredByUrl: string; popularEndpoint: string; searchEndpoint: (apiKey: string, query: string) => string; getButton: (image: ImageResult) => string; getPopularResults: (response: any) => ImageResult[]; getSearchResults: (response: any) => ImageResult[]; noRecolor = false; fetchSettings?: RequestInit; constructor({ apiKey, name, icon, color, poweredByUrl, popularEndpoint, searchEndpoint, getButton, getPopularResults, getSearchResults, noRecolor, fetchSettings, }: { name: string; icon: string; color: string; apiKey: string; poweredByUrl: string; popularEndpoint: (apiKey: string) => string; searchEndpoint: (apiKey: string, query: string) => string; getButton: (image: ImageResult) => string; getPopularResults: (response: any) => ImageResult[]; getSearchResults: (response: any) => ImageResult[]; noRecolor?: boolean; fetchSettings?: (apiKey: string) => RequestInit; }) { super(); this.name = name; this.icon = icon; this.color = color; this.apiKey = apiKey; this.noRecolor = !!noRecolor; this.poweredByUrl = poweredByUrl; this.popularEndpoint = popularEndpoint(this.apiKey); this.searchEndpoint = searchEndpoint; this.getButton = getButton; this.getPopularResults = getPopularResults; this.getSearchResults = getSearchResults; if (fetchSettings) this.fetchSettings = fetchSettings(this.apiKey); if (this.popularEndpoint) cachedFetch(this.popularEndpoint, this.fetchSettings) .then((photos) => { this.results = this.getPopularResults(photos); }) .catch(() => {}); } updateImages(params: IHandlersParams) { const imagesContainer = params.uppload.container.querySelector(".search-images"); if (imagesContainer) { imagesContainer.innerHTML = ` ${this.results.map((result) => this.getButton(result)).join("\n")} `; } } update(params: IHandlersParams) { this.updateImages(params); if (params) this.handlers(params); const loader = params.uppload.container.querySelector( ".search-loader" ) as HTMLDivElement; const container = params.uppload.container.querySelector( ".search-container" ) as HTMLDivElement; if (container) container.style.display = this.loading ? "none" : ""; if (loader) loader.style.display = this.loading ? "flex" : "none"; } template = ({ translate }: IServiceTemplateParams): string => { return `
${colorSVG(this.icon, this)}

${translate( "fetching", translate(`services.${this.name}.title`) )}

`; }; handlers = (params: IHandlersParams) => { const form = params.uppload.container.querySelector( `.search-search-form` ) as HTMLFormElement | null; if (form) { safeListen(form, "submit", (event) => { const input = params.uppload.container.querySelector( `.search-search-input` ) as HTMLInputElement | null; if (input) { const query = input.value; cachedFetch( this.searchEndpoint(this.apiKey, query), this.fetchSettings ) .then((json) => { this.results = this.getSearchResults(json); this.update(params); }) .catch(() => params.handle(new Error("errors.unable_to_search"))); } event.preventDefault(); return false; }); } this.updateImages(params); const imageButtons = params.uppload.container.querySelectorAll( ".search-images button" ); imageButtons.forEach((image) => { safeListen(image, "click", () => { const url = image.getAttribute("data-full-url"); this.loading = true; this.update(params); if (url) imageUrlToBlob(url) .then((blob) => params.next( generateFileName( blobToUpploadFile(blob), this.name, image.getAttribute("aria-label") ) ) ) .catch((error) => params.handle("errors.response_not_ok")) .then(() => (this.loading = false)); }); }); const helpButton = params.uppload.container.querySelector(".need-help-link"); if (helpButton) safeListen(helpButton, "click", () => params.showHelp(`/services/search/${this.name}`) ); }; }