/**
* @file
* @brief Feed (home) page: lazy-load masonry gallery, keyword search and random suggestions, and the New-art action.
*/
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.getAttribute("data-src");
img.setAttribute("src", src);
img.classList.remove("lazy-load");
observer.unobserve(img);
}
});
});
/**
* Images changed.
*/
function imagesChanged() {
const images = document.querySelectorAll(".lazy-load");
images.forEach((img) => {
observer.observe(img);
});
}
/**
* Clear images.
*/
function clearImages() {
const images = document.querySelectorAll(".lazy-load");
images.forEach((img) => {
try {
observer.unobserve(img);
} catch (err) {}
});
// Clear gallery
$("#page-gallery").empty();
}
/**
* Get gallery el.
* @param {string} prompt
* @param {string} imgSrc
* @param {number} width
* @param {number} height
* @param {string} name
* @returns {*}
*/
function getGalleryEl(prompt, imgSrc, width, height, name) {
return `
<a href="/single?name=${name}" rel="noopener noreferrer" class="gallery-el wide-${width} tall-${height}">
<div class="overlay">
<p>${prompt}</p>
</div>
<img data-src="${imgSrc}" class="gallery-img lazy-load"/>
</a>
`;
}
/**
* Process image feed.
* @param {object} files
*/
function processImageFeed(files) {
clearImages();
for (let i = 0; i < files.length; i++) {
// Don't list animation frames on the feed
if (files[i].animationFrameOf) continue;
// Get width and height in increments of 512
let width = files[i].width;
let height = files[i].height;
// Use upscale dimensions if there are ones
// this only happens if the file is upscaled and the original is asked to
// not be saved
if (files[i].upscaleWidth != undefined) width = files[i].upscaleWidth;
if (files[i].upscaleHeight != undefined) height = files[i].upscaleHeight;
// Convert to aspect rato
let ar = width / height;
// Determin col and row span
if (ar >= 2.0) {
width = 2;
height = 1;
} else if (ar <= 0.5) {
width = 1;
height = 2;
} else {
width = 1;
height = 1;
}
if (files[i].prompt == undefined) files[i].prompt = "";
$("#page-gallery").append(
getGalleryEl(
files[i].prompt.substring(0, 100) + "...",
files[i].imgPath,
width,
height,
files[i].name,
),
);
}
imagesChanged();
}
/**
* Load image feed.
*/
function loadImageFeed() {
$.ajax({
url: "/api/images/feed",
type: "GET",
dataType: "json",
success: function (data) {
processImageFeed(data);
},
error: function (error) {
console.log("Error:");
console.log(error);
},
});
}
/**
* Load search query.
* @param {string} query
*/
function loadSearchQuery(query) {
$.ajax({
type: "GET",
url: "/api/images/query",
data: { query },
success: function (data) {
processImageFeed(data);
},
error: function (error) {
console.log("Error:");
console.log(error);
},
});
}
/**
* Perform search.
*/
function performSearch() {
// get query and trim it
let text = $("#page-search").val();
// If it's completely empty, refresh feed, otherwise, send a query to the backend
if (text == "") loadImageFeed();
else loadSearchQuery(text);
}
/**
* Searchbox key press.
* @param {Event} event
*/
function searchboxKeyPress(event) {
const keycode = event.keyCode ? event.keyCode : event.which;
if (keycode != "13") return;
performSearch();
}
/**
* Update search suggestion.
*/
function updateSearchSuggestion() {
$.ajax({
type: "GET",
url: "/api/images/search-suggestion",
success: function (data) {
$("#page-search").attr("placeholder", data);
},
error: function (error) {
console.log("Error:");
console.log(error);
},
});
}
/**
* Perform random search.
*/
function performRandomSearch() {
// Get random placeholder text
let text = $("#page-search").attr("placeholder");
// Set it as search text
$("#page-search").val(text);
// Request new placeholder text
updateSearchSuggestion();
// Perform search
loadSearchQuery(text);
}
/**
* Home feed.
*/
function homeFeed() {
$("#page-search").val("");
loadImageFeed();
}
/**
* Update stats.
*/
function updateStats() {
$.ajax({
type: "GET",
url: "/api/images/stats",
success: function (data) {
const keywordCount = data._total.keywords;
const fileCount = data._total.files;
$("#keyword-count").text(keywordCount);
$("#image-count").text(fileCount);
},
error: function (error) {
console.log("Error:");
console.log(error);
},
});
}
// Set the interval to run every 30 seconds
setInterval(function () {
updateSearchSuggestion();
}, 15 * 1000);
/**
* Make art.
*/
function makeArt() {
let pageSearch = $("#page-search").val();
const generateSettings = {};
if (pageSearch.trim() != "") generateSettings.prompt = pageSearch.trim();
localStorage.setItem("prompt", pageSearch.trim());
localStorage.setItem("generateSettings", generateSettings);
$.ajax({
type: "POST",
url: `/api/generate-full`,
data: generateSettings,
contentType: "application/json",
success: function (data) {},
error: function (error) {
console.log("Error:");
console.log(error);
},
});
displayProgress(true);
}
$(document).ready(function () {
const params = getUrlParameters();
if (params.search != undefined) {
loadSearchQuery(params.search);
$("#page-search").val(params.search);
} else loadImageFeed();
updateSearchSuggestion();
updateStats();
$("#page-search").keypress(searchboxKeyPress);
$("#random").click(performRandomSearch);
$("#search").click(performSearch);
$("#home").click(homeFeed);
$("#make-art").click(makeArt);
});