/* a piece of flake
github:yaitskov/add-dependent-file
*/
const xhrError = (xhr) => {
if (xhr.responseText && xhr.responseText.length > 1) {
try {
const respO = JSON.parse(xhr.responseText);
if (respO.errors instanceof Array) {
return respO.errors.join("\n");
}
} catch (e) {
console.error(`${xhr.responseText} => ${e}`);
}
return xhr.responseText;
} else {
if (xhr.statusText && xhr.statusText.length > 1) {
return xhr.statusText;
} else {
return "Server is down or it is offline";
}
}
};
const xhrPost = (urlPath, payload, okCb, opsCb) => {
const xhr = new XMLHttpRequest();
xhr.open("POST", urlPath, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', 'application/json');
xhr.send(JSON.stringify(payload));
xhr.onload = (e) => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var r = null;
try {
r = JSON.parse(xhr.responseText);
} catch (je) {
opsCb(`Failed to parse response as JSON: ${je}`);
return;
}
okCb(r);
} else {
opsCb(xhrError(xhr));
}
} else {
opsCb(xhrError(xhr));
}
};
xhr.onerror = (e) => {
opsCb(`${e} => ${xhrError(xhr)}`);
};
return xhr;
};
const ready = () => {
console.log(`Document ready hook is triggered`);
const navBarBurger = document.querySelector('#navbar-burger');
const navBarBurgerCss = navBarBurger.className;
const navBarMenu = document.querySelector('#navbar-menu');
const navBarMenuCss = navBarMenu.className;
const flakeState = document.querySelector('#flake-is-not-indexed');
if (flakeState) {
document.addEventListener("visibilitychange", (event) => {
if (document.visibilityState == "visible") {
window.location.reload();
}
});
}
navBarBurger.addEventListener(
"click", (e) => {
if (navBarMenu.className.indexOf("is-active") < 0) {
navBarMenu.className = `${navBarMenu.className} is-active`;
navBarBurger.className = `${navBarBurger.className} is-active`;
} else {
navBarMenu.className = navBarMenuCss;
navBarBurger.className = navBarBurgerCss;
}
}
);
};
document.addEventListener("DOMContentLoaded", ready);
const tokenize = s => s.split(/[ \t\n]/).filter(w => w.length > 0);
const flakeViewUrl = (fu) => `/flake/${encodeURIComponent(fu)}`;
const searchFlakesBy = (pattern) => {
const searchHint = document.querySelector('#search-hint');
const flakesTbody = document.querySelector('#search-results');
const foundFlakes = document.querySelector('#found-flakes');
const errorOutput = document.querySelector('#error-output');
const noFlakesFound = document.querySelector('#no-flakes-found');
flakesTbody.innerHTML = "";
errorOutput.innerHTML = "";
errorOutput.parentNode.className = "is-hidden";
foundFlakes.className = "is-hidden";
noFlakesFound.className = "is-hidden";
console.log(`Find flakes matching pattern [${pattern}]`);
xhrPost(
"find-flakes",
{skipBroken: false, searchPattern: tokenize(pattern)},
(foundflakeUrls) => {
if (foundflakeUrls.length == 0) {
noFlakesFound.className = "";
searchHint.parentNode.className = "";
} else {
foundFlakes.className = "";
searchHint.parentNode.className = "is-hidden";
}
for (const u in foundflakeUrls) {
const tr = document.createElement("tr");
const td = document.createElement("td");
tr.appendChild(td);
const a = document.createElement("a");
td.appendChild(a);
a.setAttribute('href', flakeViewUrl(foundflakeUrls[u]));
a.innerText = foundflakeUrls[u];
flakesTbody.appendChild(tr);
}
},
(err) => {
errorOutput.innerText = err;
errorOutput.parentNode.className = "";
});
return false;
};
const rewriteUrlToGithubLink = (url) =>
url.replace(/^https:[/]{2}github[.]com[/]/, "github:");
const startSnowfall = () => {
const aniflakes = document.getElementById("aniflakes");
aniflakes.className = "ani-run";
};
const stopSnowfall = () => {
const aniflakes = document.getElementById("aniflakes");
aniflakes.className = "";
};
const submitFlake = (url) => {
const badUrl = document.getElementById("bad-url");
badUrl.className = "is-hidden";
url = rewriteUrlToGithubLink(url.trim());
if (!url.match(/^github:[a-zA-Z0-9._-]+[/][a-zA-Z0-9._-]+$/)) {
badUrl.className = "";
return false;
}
startSnowfall();
const sound = Math.random() >= 0.5 ? new Audio("/snow.mp3")
: (Math.random() >= 0.5 ? new Audio("/avalanche.mp3") : new Audio("/flush.mp3"));
console.log(`Sumbitting flake ${url}`);
const sumbittedNotification = document.getElementById("sumbitted-notification");
const errorOutputHid = document.getElementById("error-output-hid");
const errorOutput = document.getElementById("error-output");
const flakeLink = document.getElementById("flake-link");
flakeLink.setAttribute('href', '#');
errorOutput.innerText = "";
errorOutputHid.className = "is-hidden";
sumbittedNotification.className = "is-hidden";
xhrPost(
"submit-flake",
url,
(flake) => {
console.log(`${flake}`);
switch(flake.tag) {
case "SubmittedFlake":
case "FlakeIsBeingFetched":
/* play sound */
sound.onended = (e) => {
window.location = flakeViewUrl(url);
};
sound.play();
flakeLink.setAttribute('href', flakeViewUrl(url));
sumbittedNotification.className = "";
break;
case "FlakeFetched":
case "FlakeIndexed":
/* just redirect to flake view page */
flakeLink.setAttribute('href', flakeViewUrl(url));
sumbittedNotification.className = "";
setTimeout(() => window.location = flakeViewUrl(url), 1000);
break;
case "BadFlake":
default:
stopSnowfall();
errorOutput.innerText = flake.error;
errorOutputHid.className = '';
}
},
(err) => {
stopSnowfall();
errorOutput.innerText = `Submition of flake ${url} has failed: ${err}`;
errorOutputHid.className = '';
}
);
return false;
};