Merge branch 'master' of github.com:fatchan/jschan

merge-requests/208/head
fatchan 4 years ago
commit d906fc335e
  1. 43
      gulp/res/css/style.css
  2. BIN
      gulp/res/img/video.png
  3. 102
      gulp/res/js/expand.js
  4. 70
      gulp/res/js/forms.js
  5. 20
      models/forms/actionhandler.js
  6. 20
      package-lock.json
  7. 1
      views/includes/postform.pug
  8. 1
      views/pages/managebanners.pug

@ -260,6 +260,47 @@ p {
margin: 5px;
}
.upload-list {
max-height: 75px;
overflow-x: hidden;
overflow-y: auto;
max-width: 100%;
scrollbar-width: none;
border: 1px solid var(--input-borders);
margin-top: 1px;
display: none;
}
.upload-list::-webkit-scrollbar {
display: none;
}
.upload-item {
display: flex;
align-items: center;
position: relative;
}
.upload-item p {
max-width: calc(100% - 85px);
max-height: 1.5em;
overflow: hidden;
text-overflow: ellipsis;
position: absolute;
margin-left: 60px;
}
.upload-item a {
height: 50px;
display: flex;
align-items: center;
}
.upload-thumb {
width: 50px;
height: 50px;
object-fit: contain;
}
.catalog {
display:flex;
align-items:flex-start;
@ -299,6 +340,7 @@ p {
min-width: 220px;
flex-grow: 1;
flex-direction: column;
min-height: 38px;
}
.form-file {
@ -635,6 +677,7 @@ video, img {
display: flex;
image-orientation: from-image;
position:relative;
flex-direction: column;
}
.expanded {

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

@ -47,68 +47,63 @@ window.addEventListener('DOMContentLoaded', (event) => {
if (!isCatalog) { //dont expand on catalog
const thumbs = document.getElementsByClassName('post-file-src');
const toggle = function(thumb, exp, fn, src) {
if (loopEnabled) {
exp.loop = true;
} else {
exp.loop = false;
}
exp.volume = volumeLevel/100;
const close = exp.previousSibling.innerText === 'Close' ? exp.previousSibling : null;
if (thumb.style.display === 'none') {
//closing
const toggle = function(thumb, expanded, filename, src) {
if (thumb.style.display === 'none') { //closing
thumb.style.display = '';
exp.style.display = 'none';
fn.style.maxWidth = '';
if (close) {
src.style.visibility = 'visible';
close.style.display = 'none';
exp.pause();
}
} else {
//expanding
expanded.style.display = 'none';
filename.style.maxWidth = '';
} else { //expanding
thumb.style.display = 'none';
exp.style.display = '';
if (exp.offsetWidth >= fn.offsetWidth) {
fn.style.maxWidth = exp.offsetWidth+'px';
expanded.style.display = '';
if (expanded.offsetWidth >= filename.offsetWidth) {
filename.style.maxWidth = expanded.offsetWidth+'px';
}
if (close) {
}
//handle css thing for play icon on vid/audio
const close = thumb.nextSibling.innerText === 'Close' ? thumb.nextSibling : null;
if (close) {
expanded.loop = loopEnabled;
expanded.volume = volumeLevel/100;
if (src.style.visibility === 'hidden') {
src.style.visibility = 'visible';
close.style.display = 'none';
expanded.pause();
} else {
src.style.visibility = 'hidden';
close.style.display = '';
exp.play();
expanded.play();
}
}
}
const expand = function(e) {
const fileLink = this.firstChild;
const fileSrc = fileLink.href;
const type = this.dataset.type;
if (e.target.nodeName === 'VIDEO' || e.target.nodeName === 'AUDIO') {
e.stopPropagation();
return;
}
if (this.dataset.attachment == 'true') {
return; //attachments dont expand
return;
}
const thumbElement = fileLink.firstChild;
e.preventDefault();
const fileAnchor = this.firstChild;
const fileHref = fileAnchor.href;
const type = this.dataset.type;
const thumbElement = fileAnchor.firstChild;
const fileName = this.previousSibling;
const next = thumbElement.nextSibling;
const pfs = this.closest('.post-file-src');
let expandedElement;
if (next) {
if (next.innerText === 'Close') {
expandedElement = next.nextSibling;
} else {
expandedElement = next;
}
}
if (!expandedElement && thumbElement.style.opacity !== '0.5') {
let expandedElement = type === 'image' ? thumbElement.nextSibling : fileAnchor.nextSibling;
if (expandedElement) {
toggle(thumbElement, expandedElement, fileName, pfs);
} else if (thumbElement.style.opacity !== '0.5') {
let source;
fileLink.style.minWidth = fileLink.offsetWidth+'px';
fileLink.style.minHeight = fileLink.offsetHeight+'px';
switch(type) {
case 'image':
e.preventDefault();
fileAnchor.style.minWidth = fileAnchor.offsetWidth+'px';
fileAnchor.style.minHeight = fileAnchor.offsetHeight+'px';
thumbElement.style.opacity = '0.5';
thumbElement.style.cursor = 'wait'
// loading bar experiment
if (localStorage.getItem('imageloadingbars') == 'true') {
const request = new XMLHttpRequest();
request.onprogress = (e) => {
@ -123,7 +118,6 @@ window.addEventListener('DOMContentLoaded', (event) => {
}
expandedElement = document.createElement('img');
source = expandedElement;
//some jank here to try and recude any delay induced by xhr
const loaded = function(e) {
pfs.removeAttribute('data-loading');
pfs.removeAttribute('style');
@ -131,24 +125,23 @@ window.addEventListener('DOMContentLoaded', (event) => {
source.src = window.URL.createObjectURL(blob);
thumbElement.style.opacity = '';
thumbElement.style.cursor = '';
fileLink.appendChild(expandedElement);
fileAnchor.appendChild(expandedElement);
toggle(thumbElement, expandedElement, fileName, pfs);
}
request.onload = loaded;
request.responseType = 'blob';
request.open('GET', fileSrc, true);
request.open('GET', fileHref, true);
request.send(null);
} else {
// loading bar experiment
expandedElement = document.createElement('img');
source = expandedElement;
source.onload = function() {
thumbElement.style.opacity = '';
thumbElement.style.cursor = '';
fileLink.appendChild(expandedElement);
fileAnchor.appendChild(expandedElement);
toggle(thumbElement, expandedElement, fileName, pfs);
}
source.src = fileSrc;
source.src = fileHref;
}
break;
case 'video':
@ -165,19 +158,16 @@ window.addEventListener('DOMContentLoaded', (event) => {
expandedElement.controls = 'true';
source = document.createElement('source');
expandedElement.appendChild(source);
fileLink.appendChild(expandedElement);
fileLink.insertBefore(close, expandedElement);
expandedElement.style.minWidth = fileAnchor.offsetWidth+'px';
expandedElement.style.minHeight = fileAnchor.offsetHeight+'px';
pfs.appendChild(expandedElement);
fileAnchor.appendChild(close);
toggle(thumbElement, expandedElement, fileName, pfs);
source.src = fileSrc;
source.src = fileHref;
break;
deault:
return;
}
} else if (expandedElement) {
e.preventDefault();
toggle(thumbElement, expandedElement, fileName, pfs);
} else {
e.preventDefault();
}
};

@ -62,6 +62,7 @@ class formHandler {
if (this.fileInput) {
this.fileRequired = this.fileInput.required;
this.fileLabel = this.fileInput.previousSibling;
this.fileUploadList = this.fileInput.nextSibling;
this.multipleFiles = this.fileLabel.parentNode.previousSibling.firstChild.textContent.endsWith('s');
this.fileLabelText = this.fileLabel.childNodes[0];
this.fileLabel.addEventListener('dragover', e => this.fileLabelDrag(e));
@ -69,10 +70,17 @@ class formHandler {
this.fileInput.addEventListener('change', e => this.fileInputChange(e));
this.fileLabel.addEventListener('auxclick', e => this.fileLabelAuxclick(e));
}
this.messageBox.addEventListener('keydown', e => this.controlEnterSubmit(e));
form.addEventListener('paste', e => this.paste(e));
form.addEventListener('submit', e => this.formSubmit(e));
}
controlEnterSubmit(e) {
if (e.ctrlKey && e.key === 'Enter') {
this.formSubmit(e);
}
}
formSubmit(e) {
let postData;
if (this.form.getAttribute('enctype') === 'multipart/form-data') {
@ -101,8 +109,8 @@ class formHandler {
xhr.onloadstart = () => {
this.submit.value = '0%';
}
xhr.upload.onprogress = (e) => {
const progress = Math.floor((e.loaded / e.total) * 100);
xhr.upload.onprogress = (ev) => {
const progress = Math.floor((ev.loaded / ev.total) * 100);
this.submit.value = `${progress}%`;
}
xhr.onload = () => {
@ -153,9 +161,9 @@ class formHandler {
this.updateMessageBox();
this.files = [];
this.updateFilesText();
const captcha = this.form.querySelector('img');
const captcha = this.form.querySelector('.captcharefresh');
if (captcha) {
captcha.dispatchEvent(new Event('dblclick'));
captcha.dispatchEvent(new Event('click'));
}
} else {
if (xhr.status === 413) {
@ -176,8 +184,8 @@ class formHandler {
this.submit.value = this.originalSubmitText;
}
}
xhr.onerror = (e) => {
console.error(e); //why is this error fucking useless
xhr.onerror = (err) => {
console.error(err); //why is this error fucking useless
doModal({
'title': 'Error',
'message': 'Something broke'
@ -197,11 +205,17 @@ class formHandler {
this.messageBox && this.messageBox.dispatchEvent(new Event('input'));
}
//remove a single file, unused atm
removeFile(index) {
const childNode = this.fileLabel.childNodes[index+1]; //+1 because first one is fileLabelText
childNode.remove();
files.splice(index, 1);
removeFile(fileElem, name, size) {
fileElem.remove();
let fileIndex;
this.files.find((f, index) => {
if (f.name === name && f.size === size) {
fileIndex = index;
}
})
this.files.splice(fileIndex, 1);
this.updateFilesText();
console.log(this.files)
}
addFile(file) {
@ -209,6 +223,38 @@ class formHandler {
this.fileInput.removeAttribute('required');
}
this.files.push(file);
//add to upload list
const listElem = document.createElement('div');
listElem.classList.add('upload-item');
const thumb = document.createElement('img');
const name = document.createElement('p');
const remove = document.createElement('a');
name.textContent = file.name;
remove.textContent = 'X';
switch (file.type.split('/')[0]) {
case 'image':
thumb.src = URL.createObjectURL(file);
break;
case 'audio':
thumb.src = '/file/audio.png'
break;
case 'video':
thumb.src = '/file/video.png'
break;
default:
thumb.src = '/file/attachment.png'
break;
}
thumb.classList.add('upload-thumb');
remove.classList.add('close');
listElem.appendChild(thumb);
listElem.appendChild(name);
listElem.appendChild(remove);
remove.addEventListener('click', () => {
this.removeFile(listElem, file.name, file.size);
})
this.fileUploadList.appendChild(listElem);
this.fileUploadList.style.display = 'unset';
}
//show number of files on new label
@ -217,6 +263,8 @@ class formHandler {
return;
}
if (this.files && this.files.length === 0) {
this.fileUploadList.textContent = '';
this.fileUploadList.style.display = 'none';
this.fileLabelText.nodeValue = `Select/Drop/Paste file${this.multipleFiles ? 's' : ''}`;
} else {
this.fileLabelText.nodeValue = `${this.files.length} file${this.files.length > 1 ? 's' : ''} selected`;

@ -18,11 +18,19 @@ const { Posts, Boards, Modlogs } = require(__dirname+'/../../db/')
, getAffectedBoards = require(__dirname+'/../../helpers/affectedboards.js')
, buildQueue = require(__dirname+'/../../queue.js')
, { postPasswordSecret } = require(__dirname+'/../../configs/main.js')
, threadRegex = /\/[a-z0-9]+\/(?:manage\/)?thread\/(\d+)\.html/i
, { createHash, timingSafeEqual } = require('crypto');
module.exports = async (req, res, next) => {
const redirect = req.headers.referer || `/${req.params.board ? req.params.board+'/manage/reports' : 'globalmanage/recents'}.html`;
let redirect = req.headers.referer;
if (!redirect) {
if (!req.params.board) {
redirect = '/globalmanage/recent.html';
} else {
redirect = `/${req.params.board}/${req.path.endsWith('modactions') ? 'manage/reports' : 'index'}.html`;
}
}
//if user isnt staff, and they put an action that requires password, e.g. delete/spoiler, then filter posts to only matching password
if (res.locals.permLevel >= 4 && res.locals.actions.numPasswords > 0) {
@ -54,6 +62,16 @@ module.exports = async (req, res, next) => {
const deleting = req.body.delete || req.body.delete_ip_board || req.body.delete_ip_global || req.body.delete_ip_thread;
let { boardThreadMap, beforePages, threadBoards } = await getAffectedBoards(res.locals.posts, deleting);
if (deleting
&& req.params.board
&& req.headers.referer
&& boardThreadMap[req.params.board]) {
const threadRefMatch = req.headers.referer.match(threadRegex);
if (threadRefMatch && boardThreadMap[req.params.board].directThreads.has(+threadRefMatch[1])) {
redirect = `/${req.params.board}/${req.path.endsWith('modactions') ? 'manage/' : ''}index.html`;
}
}
const messages = [];
const modlogActions = []
const combinedQuery = {};

20
package-lock.json generated

@ -1064,9 +1064,9 @@
}
},
"bson": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.3.tgz",
"integrity": "sha512-TdiJxMVnodVS7r0BdL42y/pqC9cL2iKynVwA0Ho3qbsQYr428veL3l7BQyuqiw+Q5SqqoT0m4srSY/BlZ9AxXg=="
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz",
"integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q=="
},
"buffer-equal": {
"version": "1.0.0",
@ -4116,9 +4116,9 @@
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
},
"ioredis": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.16.1.tgz",
"integrity": "sha512-g76Mm9dE7BLuewncu1MimGZw5gDDjDwjoRony/VoSxSJEKAhuYncDEwYKYjtHi2NWsTNIB6XXRjE64uVa/wpKQ==",
"version": "4.16.2",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.16.2.tgz",
"integrity": "sha512-hlRK9q9K8pWpYIxUh079dWUWECiGNdI7+/AR21pgeqIBXQzjVKFnz0wXvmhEQZV3Hvv4saQpvJww9SkjwvPXZA==",
"requires": {
"cluster-key-slot": "^1.1.0",
"debug": "^4.1.1",
@ -4943,12 +4943,12 @@
}
},
"mongodb": {
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.5.tgz",
"integrity": "sha512-GCjDxR3UOltDq00Zcpzql6dQo1sVry60OXJY3TDmFc2SWFY6c8Gn1Ardidc5jDirvJrx2GC3knGOImKphbSL3A==",
"version": "3.5.6",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.6.tgz",
"integrity": "sha512-sh3q3GLDLT4QmoDLamxtAECwC3RGjq+oNuK1ENV8+tnipIavss6sMYt77hpygqlMOCt0Sla5cl7H4SKCVBCGEg==",
"requires": {
"bl": "^2.2.0",
"bson": "^1.1.1",
"bson": "^1.1.4",
"denque": "^1.4.1",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",

@ -48,6 +48,7 @@ section.form-wrapper.flex-center
span.col
include ./filelabel.pug
input#file(type='file', name='file' multiple required=fileRequired )
.upload-list
if board.settings.userPostSpoiler
label.postform-style.ph-5.ml-1.fh
input(type='checkbox', name='spoiler', value='true')

@ -26,6 +26,7 @@ block content
span.col
include ../includes/filelabel.pug
input#file(type='file', name='file' multiple required)
.upload-list
input(type='submit', value='submit')
if board.banners.length > 0
hr(size=1)

Loading…
Cancel
Save