mirror of
https://github.com/simon987/feed_viz.git
synced 2025-04-08 05:06:43 +00:00
345 lines
9.4 KiB
JavaScript
345 lines
9.4 KiB
JavaScript
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));
|
||
}
|