mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-09-13 09:26:23 -07:00
Implement frontend spoiler handling, refactor loading to reduce FOUC
This commit is contained in:
parent
13f29a5836
commit
4cca346f47
6 changed files with 119 additions and 27 deletions
1
build.py
1
build.py
|
@ -74,7 +74,6 @@ def path_info(loc):
|
|||
def update_gochan_version():
|
||||
global gochan_version
|
||||
with open("pkg/config/config.go", "r") as config:
|
||||
# GochanVersion = "4.1.0"
|
||||
config_str = config.read()
|
||||
matches = re.findall(r"\bGochanVersion\s*=\s*\"(\S+)\"", config_str)
|
||||
if len(matches) > 0:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import $ from "jquery";
|
||||
|
||||
interface BannerProps {
|
||||
interface BannerAttributes {
|
||||
src: string;
|
||||
alt: string;
|
||||
width?: number;
|
||||
|
@ -10,6 +10,12 @@ interface BannerProps {
|
|||
export function setPageBanner() {
|
||||
const slashArr = location.pathname.split("/");
|
||||
const board = (slashArr.length >= 2)?slashArr[1]:"";
|
||||
const $bannerImg = $<HTMLImageElement>("<img/>").attr({
|
||||
src: "/static/banners/gochan_go-parody.png", // placeholder, may or may not actually exist
|
||||
width: 300,
|
||||
height: 100,
|
||||
alt: "Page banner",
|
||||
}).insertBefore("header h1#board-title");
|
||||
|
||||
$.get({
|
||||
url: `${webroot}util/banner`,
|
||||
|
@ -18,17 +24,19 @@ export function setPageBanner() {
|
|||
},
|
||||
dataType: "json"
|
||||
}).then(data => {
|
||||
if(!data || data.Filename === undefined || data.Filename === "") {
|
||||
return; // no banners :(
|
||||
if((data?.Filename ?? "") === "") {
|
||||
// no banners :(
|
||||
$bannerImg.remove();
|
||||
return;
|
||||
}
|
||||
const props: BannerProps = {
|
||||
const attributes: BannerAttributes = {
|
||||
src: `${webroot}static/banners/${data.Filename}`,
|
||||
alt: "Page banner"
|
||||
};
|
||||
if(data.Width > 0 && data.Height > 0) {
|
||||
props.width = data.Width;
|
||||
props.height = data.Height;
|
||||
attributes.width = data.Width;
|
||||
attributes.height = data.Height;
|
||||
}
|
||||
$("<img/>").prop(props).insertBefore("header h1#board-title");
|
||||
$bannerImg.attr(attributes);
|
||||
});
|
||||
}
|
|
@ -306,9 +306,10 @@ export function closeQR() {
|
|||
}
|
||||
window.closeQR = closeQR;
|
||||
|
||||
$(() => {
|
||||
const board = currentBoard();
|
||||
if(board === "") return; // not on a board
|
||||
const board = currentBoard();
|
||||
if(board !== "") {
|
||||
if(getBooleanStorageVal("useqr", true))
|
||||
initQR();
|
||||
getThreadCooldown(board).then(cd => threadCooldown = cd);
|
||||
getReplyCooldown(board).then(cd => replyCooldown = cd);
|
||||
});
|
||||
}
|
|
@ -2,8 +2,8 @@ import $, { noop } from "jquery";
|
|||
|
||||
import { getBooleanStorageVal } from "../storage";
|
||||
|
||||
export let $topbar:JQuery<HTMLElement> = null;
|
||||
export let topbarHeight = 32;
|
||||
export const $topbar = $("div#topbar");
|
||||
export let topbarHeight = $topbar.height() + 4;
|
||||
|
||||
interface BeforeAfter {
|
||||
before?: any;
|
||||
|
@ -51,7 +51,6 @@ export class TopBarButton {
|
|||
* Initialize the bar at the top of the page with board links and buttons
|
||||
*/
|
||||
export function initTopBar() {
|
||||
$topbar = $("div#topbar");
|
||||
if(getBooleanStorageVal("pintopbar", true)) {
|
||||
$topbar.css({
|
||||
"z-index": "10",
|
||||
|
|
|
@ -4,7 +4,7 @@ import "./vars";
|
|||
import "./cookies";
|
||||
import "./notifications";
|
||||
import { setPageBanner } from "./dom/banners";
|
||||
import { setCustomCSS, setCustomJS, setTheme, updateExternalLinks } from "./settings";
|
||||
import { setCustomCSS, setCustomJS, setTheme, updateExternalLinks, updateSpoilerTextReveal, updateSpoilerThreadReveal } from "./settings";
|
||||
import { handleKeydown } from "./boardevents";
|
||||
import { initStaff, createStaffMenu, addStaffThreadOptions } from "./management/manage";
|
||||
import { getPageThread } from "./postinfo";
|
||||
|
@ -26,10 +26,23 @@ export function toBottom() {
|
|||
}
|
||||
window.toBottom = toBottom;
|
||||
|
||||
$(() => {
|
||||
setTheme();
|
||||
const pageThread = getPageThread();
|
||||
if(pageThread.board !== "") {
|
||||
prepareThumbnails();
|
||||
if(pageThread.op < 1) {
|
||||
updateSpoilerThreadReveal();
|
||||
updateSpoilerTextReveal();
|
||||
}
|
||||
|
||||
updateBrowseButton();
|
||||
}
|
||||
|
||||
const pageThread = getPageThread();
|
||||
setTheme();
|
||||
setCustomCSS();
|
||||
setCustomJS();
|
||||
setPageBanner();
|
||||
|
||||
$(() => {
|
||||
initStaff()
|
||||
.then((staff) => {
|
||||
if(staff?.rank < 1)
|
||||
|
@ -44,13 +57,8 @@ $(() => {
|
|||
const passwordText = $("input#postpassword").val();
|
||||
$("input#delete-password").val(passwordText);
|
||||
|
||||
setPageBanner();
|
||||
if(pageThread.board !== "") {
|
||||
prepareThumbnails();
|
||||
if(getBooleanStorageVal("useqr", true))
|
||||
initQR();
|
||||
initPostPreviews();
|
||||
updateBrowseButton();
|
||||
}
|
||||
$("div.post, div.reply").each((i, elem) => {
|
||||
addPostDropdown($(elem));
|
||||
|
@ -58,6 +66,4 @@ $(() => {
|
|||
$(document).on("keydown", handleKeydown);
|
||||
initFlags();
|
||||
updateExternalLinks();
|
||||
setCustomCSS();
|
||||
setCustomJS();
|
||||
});
|
||||
|
|
|
@ -12,6 +12,9 @@ import { updateBrowseButton } from "./dom/uploaddata";
|
|||
let $settingsButton: TopBarButton = null;
|
||||
|
||||
const settings: Map<string, Setting<boolean|number|string,HTMLElement>> = new Map();
|
||||
const spoilerThreadNotice = "This thread contains spoilers<br/>";
|
||||
const spoilerImage = "/static/spoiler.png";
|
||||
|
||||
|
||||
type ElementValue = string|number|string[];
|
||||
|
||||
|
@ -256,6 +259,80 @@ export function setCustomCSS() {
|
|||
.appendTo(document.head);
|
||||
}
|
||||
|
||||
export function updateSpoilerTextReveal() {
|
||||
const revealSpoilerText = getBooleanStorageVal("revealspoilertext", false);
|
||||
if(revealSpoilerText) {
|
||||
$(".spoiler").removeClass("spoiler").addClass("spoiler-reveal");
|
||||
} else {
|
||||
$(".spoiler").addClass("spoiler").removeClass("spoiler-reveal");
|
||||
}
|
||||
}
|
||||
|
||||
function revealSpoilerImage(el:HTMLImageElement) {
|
||||
if(el.hasAttribute("spoiler-src")) {
|
||||
el.setAttribute("src", el.getAttribute("spoiler-src"));
|
||||
el.removeAttribute("spoiler-src");
|
||||
}
|
||||
if(el.hasAttribute("spoiler-width")) {
|
||||
el.setAttribute("width", el.getAttribute("spoiler-width"));
|
||||
el.removeAttribute("spoiler-width");
|
||||
}
|
||||
if(el.hasAttribute("spoiler-height")) {
|
||||
el.setAttribute("height", el.getAttribute("spoiler-height"));
|
||||
el.removeAttribute("spoiler-height");
|
||||
}
|
||||
}
|
||||
|
||||
export function updateSpoilerThreadReveal() {
|
||||
const revealSpoilerThreads = getBooleanStorageVal("revealspoilerthreads", false);
|
||||
const $spoilerThreads = $<HTMLDivElement>(".spoiler-thread");
|
||||
const $spoilerThreadThumbs = $spoilerThreads.find<HTMLImageElement>(".op-post .thumb")
|
||||
.filter((_i, el) => !el.classList.contains("spoiler-thumb"));
|
||||
|
||||
// first reveal (or hide) the spoiler thumbs according to the setting value
|
||||
$spoilerThreadThumbs.each((i, el) => {
|
||||
if(revealSpoilerThreads) {
|
||||
revealSpoilerImage(el);
|
||||
} else {
|
||||
if(!el.hasAttribute("spoiler-src")) {
|
||||
el.setAttribute("spoiler-src", el.getAttribute("src"));
|
||||
}
|
||||
if(!el.hasAttribute("spoiler-width") && el.hasAttribute("width")) {
|
||||
el.setAttribute("spoiler-width", el.getAttribute("width"));
|
||||
el.setAttribute("width", "125px");
|
||||
}
|
||||
if(!el.hasAttribute("spoiler-height") && el.hasAttribute("height")) {
|
||||
el.setAttribute("spoiler-height", el.getAttribute("height"));
|
||||
el.setAttribute("height", "125px");
|
||||
}
|
||||
|
||||
el.setAttribute("src", path.join(webroot ?? "/", spoilerImage));
|
||||
}
|
||||
});
|
||||
if(revealSpoilerThreads) {
|
||||
$(".spoiler-notice").remove();
|
||||
$(".spoiler-thread .reply-container").show();
|
||||
$(".spoiler-thread .op-post .post-text").show();
|
||||
} else {
|
||||
$(".spoiler-thread .reply-container").hide();
|
||||
$(".spoiler-thread .op-post .post-text").hide();
|
||||
$("<div/>").addClass("spoiler-notice").append(
|
||||
spoilerThreadNotice,
|
||||
$("<button/>").text("Reveal").on("click", ev => {
|
||||
ev.stopPropagation();
|
||||
const $thread = $(ev.target).parents(".spoiler-thread");
|
||||
$thread.find(".op-post .post-text").show();
|
||||
$thread.find(".reply-container").show();
|
||||
$thread.find(".spoiler-notice").remove();
|
||||
$thread.find<HTMLImageElement>(".thumb").each((i, el) => {
|
||||
revealSpoilerImage(el);
|
||||
});
|
||||
return false;
|
||||
})
|
||||
).insertAfter($spoilerThreads.find(".op-post .post-text"));
|
||||
}
|
||||
}
|
||||
|
||||
$(() => {
|
||||
const styleOptions = [];
|
||||
for(const style of styles) {
|
||||
|
@ -268,7 +345,7 @@ $(() => {
|
|||
if(val === "" && themeElem.hasAttribute("default-href")) {
|
||||
themeElem.setAttribute("href", themeElem.getAttribute("default-href"));
|
||||
} else if(val !== "") {
|
||||
themeElem.setAttribute("href", `${webroot}css/${val}`);
|
||||
themeElem.setAttribute("href", `${webroot ?? "/"}css/${val}`);
|
||||
}
|
||||
}) as Setting);
|
||||
settings.set("pintopbar", new BooleanSetting("pintopbar", "Pin top bar", true, initTopBar));
|
||||
|
@ -279,6 +356,8 @@ $(() => {
|
|||
if(getBooleanStorageVal("useqr", true)) initQR();
|
||||
else closeQR();
|
||||
}));
|
||||
settings.set("revealspoilertext", new BooleanSetting("revealspoilertext", "Show spoiler text", false, updateSpoilerTextReveal));
|
||||
settings.set("revealspoilerthreads", new BooleanSetting("revealspoilerthreads", "Reveal spoiler threads", false, updateSpoilerThreadReveal));
|
||||
settings.set("extlinksnewtab", new BooleanSetting("extlinksnewtab", "Open external links in new tab", true, updateExternalLinks));
|
||||
settings.set("persistentqr", new BooleanSetting("persistentqr", "Persistent Quick Reply", false));
|
||||
settings.set("watcherseconds", new NumberSetting("watcherseconds", "Check watched threads every # seconds", 15, {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue