aboutsummaryrefslogtreecommitdiff
path: root/src/PrisbeamAppDisplay.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/PrisbeamAppDisplay.ts')
-rwxr-xr-xsrc/PrisbeamAppDisplay.ts455
1 files changed, 0 insertions, 455 deletions
diff --git a/src/PrisbeamAppDisplay.ts b/src/PrisbeamAppDisplay.ts
deleted file mode 100755
index e3a9ee6..0000000
--- a/src/PrisbeamAppDisplay.ts
+++ /dev/null
@@ -1,455 +0,0 @@
-import {PrisbeamApp} from "./PrisbeamApp";
-import {PrisbeamImageType} from "libprisbeam";
-import * as fs from "node:fs";
-import {PrisbeamUtilities} from "./PrisbeamUtilities";
-import {shell} from "@electron/remote";
-
-export class PrisbeamAppDisplay {
- private instance: PrisbeamApp;
-
- constructor(app: PrisbeamApp) {
- this.instance = app;
- }
-
- runUserSort(a: any, b: any) {
- if ((document.getElementById("sorting") as HTMLInputElement).value === "new") {
- return new Date(b.first_seen_at).getTime() - new Date(a.first_seen_at).getTime();
- } else if ((document.getElementById("sorting") as HTMLInputElement).value === "id") {
- return b.id - a.id;
- } else if ((document.getElementById("sorting") as HTMLInputElement).value === "popular") {
- return b.score - a.score;
- } else if ((document.getElementById("sorting") as HTMLInputElement).value === "size") {
- return b.size - a.size;
- } else if ((document.getElementById("sorting") as HTMLInputElement).value === "duration") {
- return b.duration - a.duration;
- } else if ((document.getElementById("sorting") as HTMLInputElement).value === "resolution") {
- return (b.height * b.width) - (a.height * a.width);
- } else if ((document.getElementById("sorting") as HTMLInputElement).value === "relevant") {
- return b.wilson_score - a.wilson_score;
- }
- }
-
- displayNoResults() {
- document.getElementById("search-warning").style.display = "";
- document.getElementById("pages").style.display = "none";
- document.getElementById("search-warning").innerHTML = "<b>There are no images matching your request.</b> Make sure the selected rating, filters and search query are correct and try again.";
- }
-
- getThumbnailHTML(i: any) {
- if (i['representations']['thumb'].endsWith(".webm")) i['representations']['thumb'] = i['representations']['thumb'].substring(0, i['representations']['thumb'].length - 5) + ".gif";
- let thumbnail = this.instance.dataStore.database.frontend.getImageFile(i, PrisbeamImageType.ThumbnailURL);
-
- // noinspection CssUnknownTarget
- return `
- <div
- id="image-${i.id}"
- class="
- image${i.tags.includes('safe') ? ' image-safe' : ''}
- ${i.tags.includes('questionable') ? ' image-questionable' : ''}
- ${i.tags.includes('suggestive') ? ' image-suggestive' : ''}
- ${i.tags.includes('explicit') ? ' image-explicit' : ''}
- ${i.tags.includes('grimdark') ? ' image-grimdark' : ''}
- "
- style="
- aspect-ratio: 1;
- background-color: #333;
- border-radius: 10px;
- background-position: center;
- background-size: contain;
- background-repeat: no-repeat;
- cursor: pointer;
- background-image: url(&quot;${thumbnail}&quot;);
- "
- onclick="instance.display.openImage('${i.id}')"
- ></div>
- `;
- }
-
- filterEnabledRatings(i: any) {
- return (((document.getElementById("rating-safe") as HTMLInputElement).checked && i.tags.includes("safe")) ||
- ((document.getElementById("rating-suggestive") as HTMLInputElement).checked && i.tags.includes("suggestive")) ||
- ((document.getElementById("rating-questionable") as HTMLInputElement).checked && i.tags.includes("questionable")) ||
- ((document.getElementById("rating-explicit") as HTMLInputElement).checked && i.tags.includes("explicit")) ||
- ((document.getElementById("rating-grimdark") as HTMLInputElement).checked && i.tags.includes("grimdark")))
- }
-
- getPageNumbers() {
- let _dataStore = this.instance.dataStore;
- let items = _dataStore.currentViewItems;
- let totalPages = Math.ceil(items.length / 50) + 1;
- let pageNumbers = [];
-
- if (_dataStore.page - 4 > 0) {
- pageNumbers.push(_dataStore.page - 4);
- pageNumbers.push(_dataStore.page - 3);
- pageNumbers.push(_dataStore.page - 2);
- pageNumbers.push(_dataStore.page - 1);
- } else if (_dataStore.page - 3 > 0) {
- pageNumbers.push(_dataStore.page - 3);
- pageNumbers.push(_dataStore.page - 2);
- pageNumbers.push(_dataStore.page - 1);
- } else if (_dataStore.page - 2 > 0) {
- pageNumbers.push(_dataStore.page - 2);
- pageNumbers.push(_dataStore.page - 1);
- } else if (_dataStore.page - 1 > 0) {
- pageNumbers.push(_dataStore.page - 1);
- }
-
- pageNumbers.push(_dataStore.page);
- let i = 0;
-
- while (pageNumbers.length < 9) {
- if (_dataStore.page + i + 1 <= totalPages) {
- pageNumbers.push(_dataStore.page + i + 1);
- } else {
- break;
- }
-
- i++;
- }
-
- return pageNumbers;
- }
-
- getPageHTML(page: number) {
- let length = (Math.ceil(this.instance.dataStore.currentViewItems.length / 50) + 1).toString().length;
- return "<code>" + ("0".repeat(length).substring(0, length - page.toString().length) + page.toString()) + "</code>";
- }
-
- getPageListHTML(pageNumbers: number[]) {
- let _dataStore = this.instance.dataStore;
- let items = _dataStore.currentViewItems;
- let totalPages = Math.ceil(items.length / 50) + 1;
-
- return `
- <div class="btn-group">
- <span tabindex="-1" onclick="instance.search.viewPage(1);" class="btn btn-primary ${_dataStore.page < 2 ? 'disabled' : ''}">«</span>
- <span tabindex="-1" onclick="instance.search.viewPage(${_dataStore.page - 1});" class="btn btn-primary ${_dataStore.page === 1 ? 'disabled' : ''}">‹</span>
- </div>
- <div class="btn-group">
- ${totalPages > 5 ? pageNumbers.map(i => `
- <span tabindex="-1" onclick="instance.search.viewPage(${i});" class="btn btn${i !== _dataStore.page ? '-outline' : ''}-primary">${this.getPageHTML(i)}</span>
- `).join("") : Array(totalPages).fill(null).map((_, i) => i + 1).map(i => `
- <span tabindex="-1" onclick="instance.search.viewPage(${i});" class="btn btn${i !== _dataStore.page ? '-outline' : ''}-primary">${this.getPageHTML(i)}</span>
- `).join("")}
- </div>
- <div class="btn-group">
- <span tabindex="-1" onclick="instance.search.viewPage(${_dataStore.page + 1});" class="btn btn-primary ${_dataStore.page === totalPages ? 'disabled' : ''}">›</span>
- <span tabindex="-1" onclick="instance.search.viewPage(${totalPages as number});" class="btn btn-primary ${_dataStore.page >= totalPages - 1 ? 'disabled' : ''}">»</span>
- </div>
- `;
- }
-
- updateDisplay() {
- let _dataStore = this.instance.dataStore;
- document.getElementById("search-warning").style.display = "none";
-
- if (document.getElementById("search-error").style.display === "none") {
- document.getElementById("pages").style.display = "";
- } else {
- document.getElementById("pages").style.display = "none";
- }
-
- let items = _dataStore.currentViewItems = [..._dataStore.currentView]
- .sort(this.runUserSort)
- .filter(this.filterEnabledRatings)
- .map((i) => this.getThumbnailHTML(i));
-
- if (items.length === 0 && document.getElementById("search-error").style.display === "none") this.displayNoResults();
-
- if ((document.getElementById("order") as HTMLInputElement).value === "up") {
- items = items.reverse();
- }
-
- document.getElementById("images").innerHTML = items.splice((_dataStore.page - 1) * 50, 50).join("");
- document.getElementById("pages").innerHTML = this.getPageListHTML(this.getPageNumbers());
-
- this.updateTitle();
- this.instance.bootstrapTooltips();
- }
-
- updateTitle() {
- let _dataStore = this.instance.dataStore;
- let totalPages = Math.ceil(_dataStore.currentViewItems.length / 50) + 1;
-
- if (_dataStore.searching) {
- if (_dataStore.loadedFromCache) {
- document.title = "Searching for " + (document.getElementById("search") as HTMLInputElement).value.trim() + " (page " + _dataStore.page + "/" + totalPages + ") — Prisbeam (Cached)";
- } else {
- document.title = "Searching for " + (document.getElementById("search") as HTMLInputElement).value.trim() + " (page " + _dataStore.page + "/" + totalPages + ") — Prisbeam";
- }
- } else {
- if (_dataStore.loadedFromCache) {
- document.title = "All images (page " + _dataStore.page + "/" + totalPages + ") — Prisbeam (Cached)";
- } else {
- document.title = "All images (page " + _dataStore.page + "/" + totalPages + ") — Prisbeam";
- }
- }
- }
-
- setRating(rating: string) {
- Array.from(document.querySelectorAll(".tooltip.bs-tooltip-auto")).map(i => i.outerHTML = "");
-
- (document.getElementById("rating-safe") as HTMLInputElement).checked = false;
- (document.getElementById("rating-questionable") as HTMLInputElement).checked = false;
- (document.getElementById("rating-suggestive") as HTMLInputElement).checked = false;
- (document.getElementById("rating-explicit") as HTMLInputElement).checked = false;
- (document.getElementById("rating-grimdark") as HTMLInputElement).checked = false;
-
- let code = 0;
- if (rating === "safe") code = 1;
- if (rating === "questionable") code = 2;
- if (rating === "suggestive") code = 3;
- if (rating === "explicit") code = 4;
- if (rating === "grimdark") code = 5;
-
- if (code >= 1) (document.getElementById("rating-safe") as HTMLInputElement).checked = true;
- if (code >= 2) (document.getElementById("rating-questionable") as HTMLInputElement).checked = true;
- if (code >= 3) (document.getElementById("rating-suggestive") as HTMLInputElement).checked = true;
- if (code >= 4) (document.getElementById("rating-explicit") as HTMLInputElement).checked = true;
- if (code >= 5) (document.getElementById("rating-grimdark") as HTMLInputElement).checked = true;
- }
-
- highlightZone(id: string, state: boolean) {
- if (state) {
- document.getElementById("preview-zone-" + id).classList.add("hover");
- document.getElementById("preview-tag-zone-" + id).classList.add("hover");
- } else {
- document.getElementById("preview-zone-" + id).classList.remove("hover");
- document.getElementById("preview-tag-zone-" + id).classList.remove("hover");
- }
- }
-
- buildImageTitle() {
- let _dataStore = this.instance.dataStore;
-
- return "Image #<span class='selectable'>" +
- (_dataStore.currentImage.source_id ?? _dataStore.currentImage.id) +
- (_dataStore.currentImage.source_name
- ? "</span> (<span class='selectable'>" + _dataStore.currentImage.source_name + "</span>)"
- : "") +
- "" +
- PrisbeamUtilities.getMimeBadge(_dataStore.currentImage.mime_type)
- }
-
- displayImageSize() {
- let _dataStore = this.instance.dataStore;
- let size = 0;
- let sizeExplanation = [];
-
- let file = _dataStore.database.frontend.getImageFile(_dataStore.currentImage, PrisbeamImageType.ViewFile);
- let thumb = _dataStore.database.frontend.getImageFile(_dataStore.currentImage, PrisbeamImageType.ThumbnailFile);
-
- if (file) {
- let cSize = fs.lstatSync(file).size;
- size += cSize;
- sizeExplanation.push("Image: " + PrisbeamUtilities.formatSize(cSize));
- }
-
- if (thumb) {
- let cSize = fs.lstatSync(thumb).size;
- size += cSize;
- sizeExplanation.push("Thumbnail: " + PrisbeamUtilities.formatSize(cSize));
- }
-
- let cSize = JSON.stringify(_dataStore.currentImage).length;
- size += cSize;
- sizeExplanation.push("Metadata: " + PrisbeamUtilities.formatSize(cSize));
-
- document.getElementById("preview-size").innerHTML =
- "<span data-bs-toggle='tooltip' data-bs-html='true' title='" + sizeExplanation.join("<br>") + "'>" +
- PrisbeamUtilities.formatSize(size) + "</span>";
- }
-
- categorySortingNumber(cat: string) {
- if (cat === "error") return 0;
- if (cat === "rating") return 1;
- if (cat === "origin") return 2;
- if (cat === "character") return 3;
- if (cat === "oc") return 4;
- if (cat === "species") return 5;
- if (cat === "body-type") return 6;
- if (cat === "content-official") return 7;
- if (cat === "content-fanmade") return 8;
- if (cat === "spoiler") return 9;
- return 999;
- }
-
- async getImpliedTags() {
- let _dataStore = this.instance.dataStore;
-
- let categories = {};
- let implied = [];
- let impliedNames = [];
-
- for (let id of _dataStore.currentImage.tag_ids) {
- implied.push(...(await _dataStore.database.frontend.getImpliedTagIdsFromId(id)).filter(i => !_dataStore.currentImage.tag_ids.includes(i)));
- impliedNames.push(...(await _dataStore.database.frontend.getImpliedTagNamesFromId(id)).filter(i => !_dataStore.currentImage.tags.includes(i)));
- }
-
- for (let id of implied) {
- categories[id] = (await _dataStore.database._sql("SELECT category FROM tags WHERE id=" + id))[0]['category'];
- }
-
- implied = [...new Set(implied)];
- impliedNames = [...new Set(impliedNames)];
-
- let impliedTags = impliedNames.map((i: string, j: number) => [i, implied[j], categories[implied[j]]]);
-
- return impliedTags.sort((a, b) => {
- return a[0].localeCompare(b[0]);
- }).sort((a, b) => {
- return this.categorySortingNumber(a[2]) - this.categorySortingNumber(b[2]);
- });
- }
-
- async getTags() {
- let _dataStore = this.instance.dataStore;
- let categories = {};
-
- for (let id of _dataStore.currentImage.tag_ids) {
- categories[id] = (await _dataStore.database._sql("SELECT category FROM tags WHERE id=" + id))[0]['category'];
- }
-
- let tags = _dataStore.currentImage.tags.map((i: string, j: number) => [i, _dataStore.currentImage.tag_ids[j], categories[_dataStore.currentImage.tag_ids[j]]]);
-
- return tags.sort((a: string, b: string) => {
- return a[0].localeCompare(b[0]);
- }).sort((a: string, b: string) => {
- return this.categorySortingNumber(a[2]) - this.categorySortingNumber(b[2]);
- });
- }
-
- async displayTags() {
- let tags = await this.getTags();
- let impliedTags = await this.getImpliedTags();
-
- document.getElementById("preview-tags").innerHTML = tags.map((i: any[]) =>
- "<a class='preview-tag preview-tag-" +
- (i[2] ?? "unknown") +
- "' onclick='instance.search.startTagSearch(decodeURIComponent(atob(\"" + btoa(encodeURIComponent(i[0])) + "\")))'>" +
- i[0] + "</a>"
- ).join("<wbr>") +
- impliedTags.map(i =>
- "<a class='preview-tag preview-tag-implied preview-tag-" +
- (i[2] ?? "unknown") +
- "' onclick='searchForTag(decodeURIComponent(atob(\"" + btoa(encodeURIComponent(i[0])) + "\")))'>" +
- i[0] + "</a>"
- ).join("<wbr>");
- }
-
- async initializeImageUI(id: string) {
- let _dataStore = this.instance.dataStore;
-
- _dataStore.modal.show();
- _dataStore.currentImage = await _dataStore.database.frontend.getImage(id);
- _dataStore.currentImageClasses = [];
- document.getElementById("preview-zones").innerHTML = "";
-
- document.getElementById("preview-parts-loader").style.display = "";
- document.getElementById("preview-parts-none").style.display = "none";
- document.getElementById("preview-parts-unsupported").style.display = "none";
- document.getElementById("preview-parts-list").style.display = "none";
- document.title = "Viewing image #" + (_dataStore.currentImage.source_id ?? id) + " — " + document.title;
- document.getElementById("preview-title").innerHTML = this.buildImageTitle();
- document.getElementById("preview-date").innerHTML = "Uploaded <span data-bs-toggle='tooltip' title='" + new Date(_dataStore.currentImage.created_at * 1000).toString() + "'>" + PrisbeamUtilities.timeAgo(_dataStore.currentImage.created_at * 1000) + "</span>";
- document.getElementById("preview-resolution").innerText = _dataStore.currentImage.width + " × " + _dataStore.currentImage.height;
- document.getElementById("preview-source-cta").innerText = "View on " + _dataStore.currentImage.source_name ?? "Derpibooru";
- }
-
- getCreditDescriptors() {
- let descriptors = {
- artists: [], editors: [], generators: [], photographers: [], prompters: [], colorists: []
- };
- let finalDescriptors = [];
-
- for (let tag of this.instance.dataStore.currentImage.tags) {
- if (tag.startsWith("artist:")) descriptors.artists.push(tag.substring(7));
- if (tag.startsWith("editor:")) descriptors.editors.push(tag.substring(7));
- if (tag.startsWith("generator:")) descriptors.generators.push(tag.substring(10));
- if (tag.startsWith("photographer:")) descriptors.photographers.push(tag.substring(13));
- if (tag.startsWith("prompter:")) descriptors.prompters.push(tag.substring(9));
- if (tag.startsWith("colorist:")) descriptors.colorists.push(tag.substring(9));
- }
-
- if (descriptors.artists.length > 0) finalDescriptors.push("artist" + (descriptors.artists.length > 1 ? "s" : "") + ": " + descriptors.artists.join(""));
- if (descriptors.editors.length > 0) finalDescriptors.push("editor" + (descriptors.editors.length > 1 ? "s" : "") + ": " + descriptors.editors.join(""));
- if (descriptors.generators.length > 0) finalDescriptors.push("generator" + (descriptors.generators.length > 1 ? "s" : "") + ": " + descriptors.generators.join(""));
- if (descriptors.photographers.length > 0) finalDescriptors.push("photographer" + (descriptors.photographers.length > 1 ? "s" : "") + ": " + descriptors.photographers.join(""));
- if (descriptors.prompters.length > 0) finalDescriptors.push("prompter" + (descriptors.prompters.length > 1 ? "s" : "") + ": " + descriptors.prompters.join(""));
- if (descriptors.colorists.length > 0) finalDescriptors.push("colorist" + (descriptors.colorists.length > 1 ? "s" : "") + ": " + descriptors.colorists.join(""));
-
- if (finalDescriptors[0]) finalDescriptors[0] = finalDescriptors[0].substring(0, 1).toUpperCase() + finalDescriptors[0].substring(1);
-
- return finalDescriptors;
- }
-
- displayCredits() {
- let _dataStore = this.instance.dataStore;
- let artist = "Anonymous artist";
- let finalDescriptors = this.getCreditDescriptors();
- if (finalDescriptors.length > 0) artist = finalDescriptors.join("; ");
-
- if (_dataStore.currentImage.tags.includes("official")) {
- if (finalDescriptors.length > 0) {
- artist = finalDescriptors.join("; ") + " (official content)";
- } else {
- artist = "Official Hasbro content";
- }
- }
-
- if (_dataStore.currentImage.tags.includes("artist needed")) {
- artist = "Unknown artist";
- }
-
- document.getElementById("preview-artist").innerText = artist;
- }
-
- displayScore() {
- let _dataStore = this.instance.dataStore;
-
- if (_dataStore.currentImage.score !== 0) {
- try { document.getElementById("preview-score").outerHTML = ""; } catch (e) {}
- document.getElementById("preview-statistics").insertAdjacentHTML("afterbegin", `<div class="list-group-item" id="preview-score" style="font-weight: bold;"></div>`);
-
- if (_dataStore.currentImage.faves > 0) {
- document.getElementById("preview-score").innerText = _dataStore.currentImage.faves + " favorites · " + _dataStore.currentImage.score + " points (" + _dataStore.currentImage.upvotes + " up, " + _dataStore.currentImage.downvotes + " down)";
- } else {
- document.getElementById("preview-score").innerText = _dataStore.currentImage.score + " points (" + _dataStore.currentImage.upvotes + " up, " + _dataStore.currentImage.downvotes + " down)";
- }
- } else {
- try { document.getElementById("preview-score").outerHTML = ""; } catch (e) {}
- }
- }
-
- displayViewer() {
- let _dataStore = this.instance.dataStore;
- let url = _dataStore.database.frontend.getImageFile(_dataStore.currentImage, PrisbeamImageType.ViewURL)
-
- if (_dataStore.currentImage.mime_type.startsWith("video/")) {
- document.getElementById("preview-content").innerHTML = `
- <video id="preview-content-inner" loop muted autoplay controls src="${url}" style="max-width: 100%; max-height: 80vh; margin-left: auto; margin-right: auto; display: block;"></video>
- `;
- } else {
- document.getElementById("preview-content").innerHTML = `
- <img alt="" id="preview-content-inner" src="${url}" style="max-width: 100%; max-height: calc((100vh - 1.75rem * 2) - 71px); margin-left: auto; margin-right: auto; display: block;">
- `;
- }
- }
-
- async openImage(id: string) {
- await this.initializeImageUI(id);
- this.displayImageSize();
- await this.displayTags();
- this.displayCredits();
- this.displayScore();
- this.displayViewer();
- this.instance.ai.displayClasses(id);
- this.instance.bootstrapTooltips();
- }
-
- openImageOnSource() {
- let image = this.instance.dataStore.currentImage;
- shell.openExternal(image['source'].replace("%s", image['source_id']));
- }
-}