feed_viz/js/main.js
2019-12-19 11:11:31 -05:00

345 lines
9.4 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

let maxImages = 300;
let currentImages = 0;
let socket = undefined;
let colCount = 4;
let cols = [];
let colHeights = [];
let loadNsfw = false;
let storage = window.localStorage;
let chips;
let exchange = "reddit";
let helpModal;
window.onload = function () {
M.Tabs.init(document.getElementById("tabs"), {});
M.FormSelect.init(document.querySelectorAll("select"), {});
M.Chips.init(document.querySelectorAll(".chips"), {
placeholder: "Type topic and press 'Enter'",
secondaryPlaceholder: "+Topic",
onChipAdd: function (elem, chip) {
if (!validateTopic(chip.firstChild.wholeText)) {
helpModal.open();
chips.deleteChip(chips.chipsData.length - 1);
}
}
});
chips = M.Chips.getInstance(document.getElementById("chips"));
M.Modal.init(document.querySelectorAll(".modal"), {});
helpModal = M.Modal.getInstance(document.getElementById("help"));
setDefaultPresets();
updatePresets();
const storageColCount = storage.getItem("col-count");
if (storageColCount) {
document.getElementById("col-count").value = storageColCount;
colCount = storageColCount;
}
const storageMaxImages = storage.getItem("max-images");
if (storageMaxImages) {
document.getElementById("max-images").value = storageMaxImages;
maxImages = storageMaxImages;
}
if (storage.getItem("nsfw") === "true") {
document.getElementById("nsfw").checked = true;
loadNsfw = true;
}
};
function resetGallery() {
let out = document.getElementById("output");
while (out.hasChildNodes()) {
out.removeChild(out.lastChild);
}
cols = [];
colHeights = [];
currentImages = 0;
document.getElementById("output").appendChild(createGallery(colCount));
}
function onConnectClick() {
document.getElementById("topics")
.dispatchEvent(
new KeyboardEvent(
"keydown",
{bubbles: true, cancelable: true, key: "Enter", keyCode: 13}
)
);
if (socket) {
socket.close()
}
document.getElementById("connect").innerHTML = "Connecting..";
document.getElementById("connect").classList.add("connecting");
resetGallery();
let topics = chips.chipsData.map(chip => chip.tag);
if (topics.length === 0) {
alert("You must specify at least one topic");
return
}
connect(exchange, topics);
}
function connect(exchange, topics) {
socket = new WebSocket("wss://feed.the-eye.eu/socket");
socket.onmessage = msg => {
let items = JSON.parse(msg.data);
items.forEach(j => {
if (j._urls && ((loadNsfw && j.over_18) || !j.over_18 || !j.hasOwnProperty("over_18"))) {
j._urls
.filter(url => /http?s:\/\/.*(.jpg|.jpeg|.bmp|.png|.gif|.jpeg:orig|.jpg:orig)$/.test(url))
.forEach(url => appendToGallery(createImage(url, j)));
}
})
};
socket.onopen = () => {
socket.send(JSON.stringify({
exchange: exchange,
topics: topics
}));
document.getElementById("connect").innerHTML = "Connected";
document.getElementById("connect").classList.remove("connecting");
document.getElementById("connect").classList.remove("disconnected");
document.getElementById("connect").classList.add("connected");
};
socket.onclose = (e) => {
if (socket.readyState === socket.CLOSING || socket.readyState === socket.CLOSED) {
console.log(socket);
console.log(e);
document.getElementById("connect").innerHTML = "Disconnected";
document.getElementById("connect").classList.remove("connected");
document.getElementById("connect").classList.remove("connecting");
document.getElementById("connect").classList.add("disconnected");
}
};
socket.onerror = (e) => {
console.log(e)
};
window.onbeforeunload = function () {
socket.close();
}
}
function createImage(src, j) {
const img = document.createElement("img");
img.setAttribute("class", "img");
img.setAttribute("src", src);
if (exchange === "reddit") {
img.onclick = function () {
window.open("https://reddit.com/" + j["id"]);
};
}
img.onerror = function () {
//Don't display broken images
img.remove();
return true;
};
return img;
}
function createGallery(count) {
const gallery = document.createElement('div');
gallery.setAttribute('class', 'row');
for (let i = 0; i < count; i++) {
let col = document.createElement('div');
col.setAttribute('class', `col s${Math.floor(12 / count)}`);
gallery.appendChild(col);
cols.push(col);
colHeights.push(0);
}
return gallery;
}
function popRow() {
for (let i = 0; i < colCount; i++) {
if (cols[i].hasChildNodes()) {
colHeights[i] -= cols[i].lastChild.height;
cols[i].lastChild.remove();
currentImages -= 1;
}
}
}
function appendToGallery(child) {
currentImages++;
if (currentImages > maxImages) {
popRow()
}
let minHeight = Number.MAX_VALUE;
let min = 0;
for (let i = 0; i < cols.length; i++) {
if (colHeights[i] < minHeight) {
minHeight = colHeights[i];
min = i;
}
}
cols[min].prepend(child);
if (!child.height) {
colHeights[min] += 2400 / colCount;
child.onload = function () {
colHeights[min] += this.height;
colHeights[min] -= 2400 / colCount;
};
} else {
colHeights[min] += child.height;
}
}
function getPreset(name) {
let j = JSON.parse(storage.getItem("presets"));
return j[name]
}
function setPreset(name, topics) {
if (storage.getItem("presets") === null) {
storage.setItem("presets", "{}")
}
let j = JSON.parse(storage.getItem("presets"));
j[name] = topics;
storage.setItem("presets", JSON.stringify(j))
}
function setDefaultPresets() {
setPreset("Reddit animals", ["*.aww", "*.awww", "*.cats", "*.eyebleach", "*.cute", "*.dogs",
"*.koalas", "*.lynxes", "comment.dogs", "*.dogpictures", "submission.puppies", "submission.puppy",
"submission.doge"]);
setPreset("Reddit birds", ["submission.birds", "submission.bird", "submission.parrots",
"submission.birdpics", "submission.birdwatching", "submission.birding", "submission.birdphotography"]);
setPreset("Reddit ocean", ["*.ocean", "*.oceangifs", "*.swimming",
"*.algae", "*.costalforaging", "*.earthscience", "*.freediving",
"*.hydrology", "*.lifeaquatic", "*.marinelife", "*.octopuses",
"*.scuba", "*.seacreatureporn", "*.seaweed", "*.sharks",
"*.shipwrecks", "*.water", "*.whales", "*.underwaterphotography"]);
}
function onPresetSelect() {
let selection = document.getElementById("presets").value;
while (chips.chipsData.length > 0) {
chips.deleteChip(0)
}
getPreset(selection).forEach(topic => {
chips.addChip({tag: topic})
});
M.toast({html: "Loaded preset"})
}
function onSavePresetClick() {
let name = document.getElementById("preset-name").value;
let topics = chips.chipsData.map(chip => chip.tag);
if (name === "") {
alert("Invalid preset name");
return;
}
setPreset(name, topics);
updatePresets();
M.toast({html: "Saved preset"})
}
function updatePresets() {
let j = JSON.parse(storage.getItem("presets"));
const select = document.getElementById("presets");
while (select.hasChildNodes()) {
select.removeChild(select.lastChild);
}
const opt = document.createElement("option");
opt.setAttribute("disabled", "");
opt.setAttribute("value", "-");
opt.appendChild(document.createTextNode("Load Preset"));
select.appendChild(opt);
Object.keys(j).forEach(key => {
const opt = document.createElement("option");
opt.setAttribute("value", key);
opt.appendChild(document.createTextNode(key));
select.appendChild(opt)
});
select.value = "-"
}
function onMaxImageChange() {
maxImages = document.getElementById("max-images").value;
storage.setItem("max-images", maxImages);
}
function onExchangeChange() {
exchange = document.getElementById("exchange").value;
document.getElementById("nsfw").disabled = exchange !== "reddit"
}
function onNsfwChange() {
loadNsfw = document.getElementById("nsfw").checked;
storage.setItem("nsfw", loadNsfw);
}
function onColCountChange() {
colCount = document.getElementById("col-count").value;
storage.setItem("col-count", colCount);
let images = [];
const row = document.getElementById("output").firstChild;
if (!row) {
return
}
while (row.hasChildNodes()) {
let col = row.lastChild;
while (col.hasChildNodes()) {
images.push(col.lastChild);
col.removeChild(col.lastChild);
}
row.removeChild(col);
}
resetGallery();
images.forEach(img => appendToGallery(img));
}
function validateTopic(topic) {
return (exchange === "reddit" && /^(#$|((submission|comment|\*)\.(\w+|\*)$))/.test(topic)) ||
(exchange === "chan" && /^(#$|#\.\w+$|(4chan|lainchan|uboachan|22chan|wizchan|1chan|\*)\.(#$|(post|thread|\*)\.(\w+|\*)$))/.test(topic));
}