diff options
Diffstat (limited to 'src/PrisbeamAppDisplay.ts')
-rwxr-xr-x | src/PrisbeamAppDisplay.ts | 455 |
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("${thumbnail}"); - " - 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'])); - } -} |