Start on changing how post hiding works, rename to filters

still TOOD: make them toggleable, and some more testing
but so far works, and post updates are handled
renamed 'hidden' localstorage to prevent issues for previous users
merge-requests/208/head
Thomas Lynch 4 years ago
parent 18b58202e7
commit 7c4e8f9c2e
  1. 62
      gulp/res/js/csstoggles.js
  2. 145
      gulp/res/js/filters.js
  3. 188
      gulp/res/js/hide.js
  4. 2
      gulp/res/js/hover.js
  5. 7
      gulp/res/js/localstorage.js
  6. 8
      gulpfile.js
  7. 10
      views/mixins/post.pug

@ -0,0 +1,62 @@
const renderCSSLink = document.createElement('style');
renderCSSLink.type = 'text/css';
renderCSSLink.id = 'rendercss';
document.head.appendChild(renderCSSLink);
const renderSheet = renderCSSLink.sheet;
const rulesKey = renderSheet.rules ? 'rules' : 'cssRules';
class CssToggle {
constructor (settingId, localStorageKey, localStorageDefault, settingCss) {
this.localStorageKey = localStorageKey;
this.localStorageDefault = localStorageDefault;
setDefaultLocalStorage(this.localStorageKey, this.localStorageDefault);
this.settingBoolean = localStorage.getItem(this.localStorageKey) == 'true';
this.settingCss = settingCss;
window.addEventListener('settingsReady', () => {
//on event fire, set boolean to correct checked stats
this.setting = document.getElementById(settingId);
this.setting.checked = this.settingBoolean;
this.setting.addEventListener('change', () => {
this.toggle();
}, false);
});
this.apply();
}
toggle () {
this.settingBoolean = !this.settingBoolean;
console.log('toggling', this.localStorageKey, this.settingBoolean);
this.apply();
setLocalStorage(this.localStorageKey, this.settingBoolean);
}
apply () {
if (this.settingBoolean) {
renderSheet.insertRule(this.settingCss);
} else {
for (let i = 0; i < renderSheet[rulesKey].length; i++) {
if (renderSheet[rulesKey][i].selectorText == this.settingCss.split(' {')[0]) {
renderSheet.deleteRule(i);
}
}
}
}
};
//define the css
const hidePostStubsCss = `.post-container.hidden, .catalog-tile.hidden { visibility: hidden;margin-top: -1.5em;height: 0; }`;
const hideThumbnailsCss = `.file-thumb, .catalog-thumb { visibility: hidden !important; }`;
const hideRecursiveCss = `.op.hidden ~ .anchor, .op.hidden ~ .post-container { display: none; }`;
const heightUnlimitCss = `img, video { max-height: unset; }`;
const crispCss = `img { image-rendering: crisp-edges; }`;
const nonColorIdsCss = `.user-id { background: transparent none repeat scroll 0% 0% !important; border-color: transparent; text-shadow: none; color: var(--font-color); }`;
const alwaysShowSpoilersCss = `.spoiler { color: var(--font-color) !important; background: transparent none repeat scroll 0% 0%; outline: 1px solid black; cursor: auto; }`;
const smoothScrollingCss = `html { scroll-behavior: smooth; }`;
//make classes with css
new CssToggle('hiderecursive-setting', 'hiderecursive', settings.hideRecursive, hideRecursiveCss);
new CssToggle('heightlimit-setting', 'heightlimit', settings.heightUnlimit, heightUnlimitCss);
new CssToggle('crispimages-setting', 'crispimages', settings.crispImages, crispCss);
new CssToggle('hidethumbnails-setting', 'hidethumbnails', settings.hideThumbnails, hideThumbnailsCss);
new CssToggle('noncolorids-setting', 'noncolorids', settings.nonColorIds, nonColorIdsCss);
new CssToggle('alwaysshowspoilers-setting', 'alwaysshowspoilers', settings.alwaysShowSpoilers, alwaysShowSpoilersCss);
new CssToggle('hidepoststubs-setting', 'hidepoststubs', settings.hidePostStubs, hidePostStubsCss);
new CssToggle('smoothscrolling-setting', 'smoothscrolling', settings.smoothScrolling, smoothScrollingCss);

@ -0,0 +1,145 @@
const fileInput = document.getElementById('file');
if (fileInput) {
//not using display: none because we still want to show the browser prompt for a "required" file
fileInput.style.position = 'absolute';
fileInput.style.border = 'none';
fileInput.style.height = '0';
fileInput.style.width = '0';
fileInput.style.opacity = '0';
}
//lists separate until i come up with something better
let hidePostsList;
let { hiddenSingle, filteredId, filteredName, filteredTripcode } = JSON.parse(localStorage.getItem('filters'));
hiddenSingle = new Set(hiddenSingle);
filteredId = new Set(filteredId);
filteredName = new Set(filteredName);
filteredTripcode = new Set(filteredTripcode);
const updateSavedFilters = () => {
hidePostsList.value = [...hiddenSingle, ...filteredId, ...filteredName, ...filteredTripcode];
setLocalStorage('filters', JSON.stringify({
hiddenSingle: [...hiddenSingle],
filteredId: [...filteredId],
filteredName: [...filteredName],
filteredTripcode: [...filteredTripcode],
}));
}
const togglePostsHidden = (posts, state) => {
for (let elem of posts) {
elem.classList[state ? 'add' : 'remove']('hidden');
}
}
const getPostsByFilter = (type, data) => {
let posts = [];
switch (type) {
case 'hide':
const post = document.querySelector(`[data-board="${data.board}"][data-post-id="${data.postId}"]`);
posts = post ? [post] : [];
break;
case 'id':
posts = document.querySelectorAll(`[data-user-id="${data.userId}"]`);
break;
case 'name':
posts = document.querySelectorAll(`[data-name="${CSS.escape(data.name)}"]`);
break;
case 'tripcode':
posts = document.querySelectorAll(`[data-tripcode="${CSS.escape(data.tripcode)}"]`);
break;
default:
break;
}
return [...posts]
}
const setFilterState = (type, data, state) => {
switch (type) {
case 'hide':
hiddenSingle[state ? 'add' : 'delete'](`${data.board}-${data.postId}`);
break;
case 'id':
filteredId[state ? 'add' : 'delete'](data.userId);
break;
case 'name':
filteredName[state ? 'add' : 'delete'](data.name);
break;
case 'tripcode':
filteredTripcode[state ? 'add' : 'delete'](data.tripcode);
break;
default:
break;
}
}
const postMenuChange = function(e) {
const postContainer = this.parentElement.parentElement.parentElement;
const filterType = this.value;
const posts = getPostsByFilter(filterType, postContainer.dataset);
if (posts.length === 0) { return; }
//TODO: unhiding
setFilterState(filterType, postContainer.dataset, true);
this.value = '';
togglePostsHidden(posts, true);
updateSavedFilters();
}
for (let menu of document.getElementsByClassName('postmenu')) {
menu.value = '';
menu.addEventListener('change', postMenuChange, false);
}
const getHiddenElems = () => {
let posts = [];
for (let elem of hiddenSingle) {
const [board, postId] = elem.split('-');
posts = posts.concat(getPostsByFilter('hide', { board, postId }));
}
for (let id of filteredId) {
posts = posts.concat(getPostsByFilter('id', { userId: id }));
}
for (let name of filteredName) {
posts = posts.concat(getPostsByFilter('name', { name }));
}
for (let tripcode of filteredTripcode) {
posts = posts.concat(getPostsByFilter('tripcode', { tripcode }));
}
return posts;
}
togglePostsHidden(getHiddenElems(), true);
window.addEventListener('addPost', function(e) {
const post = e.detail.post;
const { board, postId, userId, name, tripcode } = post.dataset;
if (filteredId.has(userId)
|| filteredName.has(name)
|| filteredTripcode.has(tripcode)) {
post.classList.add('hidden');
}
const menu = post.querySelector('.postmenu');
menu.value = '';
menu.addEventListener('change', postMenuChange, false);
});
window.addEventListener('settingsReady', function(e) {
hidePostsList = document.getElementById('hiddenpostslist-setting');
hidePostsList.value = [...hiddenSingle, ...filteredId, ...filteredName, ...filteredTripcode];
const hidePostsListClearButton = document.getElementById('hiddenpostslist-clear');
const clearhidePostsList = () => {
togglePostsHidden(getHiddenElems(), false);
hidePostsList.value = '';
hiddenSingle = new Set();
filteredId = new Set();
filteredName = new Set();
filteredTripcode = new Set();
updateSavedFilters();
console.log('cleared hidden posts');
}
hidePostsListClearButton.addEventListener('click', clearhidePostsList, false);
});

@ -1,188 +0,0 @@
const fileInput = document.getElementById('file');
if (fileInput) {
fileInput.style.position = 'absolute';
fileInput.style.border = 'none';
fileInput.style.height = '0';
fileInput.style.width = '0';
fileInput.style.opacity = '0';
}
let hidePostsList;
let hidden = new Set(JSON.parse(localStorage.getItem('hidden')));
const setHidden = (posts, hide) => {
if (posts && posts.length > 0) {
for (let i = 0; i < posts.length; i++) {
const post = posts[i];
if (!post.dataset) {
continue;
}
const menu = post.querySelector('.postmenu');
if (menu) {
for (let i = 0; i < menu.children.length; i++) {
if (hide) {
menu.children[i].innerText = 'Un'+menu.children[i].originalText;
} else {
menu.children[i].innerText = menu.children[i].originalText;
}
}
}
const { board, postId, userId } = post.dataset;
if (hide) {
post.classList.add('hidden');
} else {
hidden.delete(`${board}-${postId}`);
post.classList.remove('hidden');
}
}
}
}
const changeOption = function(e) {
const option = this.value;
const postContainer = this.parentElement.parentElement.parentElement;
const { board, postId, userId } = postContainer.dataset;
let posts = [postContainer];
const hiding = !option.startsWith('Un');
if (option.endsWith('ID')) {
const idPosts = document.querySelectorAll(`[data-user-id="${userId}"]`);
if (idPosts && idPosts.length > 0) {
posts = idPosts;
}
if (hiding) {
hidden.add(userId);
} else {
hidden.delete(userId);
}
}
if (hiding) {
hidden.add(`${board}-${postId}`);
}
this.value = '';
setHidden(posts, hiding);
const hiddenArray = [...hidden];
hidePostsList.value = hiddenArray.toString();
setLocalStorage('hidden', JSON.stringify(hiddenArray));
}
for (let menu of document.getElementsByClassName('postmenu')) {
menu.value = '';
for (let i = 0; i < menu.children.length; i++) {
menu.children[i].originalText = menu.children[i].innerText;
}
menu.addEventListener('change', changeOption, false);
}
const getHiddenElems = () => {
let posts = [];
for (let elem of hidden) {
if (elem.includes('-')) {
const [board, postId] = elem.split('-');
const post = document.querySelector(`[data-board="${board}"][data-post-id="${postId}"]`);
if (post) {
posts.push(post);
}
} else {
const idPosts = document.querySelectorAll(`[data-user-id="${elem}"]`);
if (idPosts && idPosts.length > 0) {
posts = posts.concat(idPosts);
}
}
}
return posts;
}
setHidden(getHiddenElems(), true);
const renderCSSLink = document.createElement('style');
renderCSSLink.type = 'text/css';
renderCSSLink.id = 'rendercss';
document.head.appendChild(renderCSSLink);
const renderSheet = renderCSSLink.sheet;
const rulesKey = renderSheet.rules ? 'rules' : 'cssRules';
class CssToggle {
constructor (settingId, localStorageKey, localStorageDefault, settingCss) {
this.localStorageKey = localStorageKey;
this.localStorageDefault = localStorageDefault;
setDefaultLocalStorage(this.localStorageKey, this.localStorageDefault);
this.settingBoolean = localStorage.getItem(this.localStorageKey) == 'true';
this.settingCss = settingCss;
window.addEventListener('settingsReady', () => {
//on event fire, set boolean to correct checked stats
this.setting = document.getElementById(settingId);
this.setting.checked = this.settingBoolean;
this.setting.addEventListener('change', () => {
this.toggle();
}, false);
});
this.apply();
}
toggle () {
this.settingBoolean = !this.settingBoolean;
console.log('toggling', this.localStorageKey, this.settingBoolean);
this.apply();
setLocalStorage(this.localStorageKey, this.settingBoolean);
}
apply () {
if (this.settingBoolean) {
renderSheet.insertRule(this.settingCss);
} else {
for (let i = 0; i < renderSheet[rulesKey].length; i++) {
if (renderSheet[rulesKey][i].selectorText == this.settingCss.split(' {')[0]) {
renderSheet.deleteRule(i);
}
}
}
}
};
//define the css
const hidePostStubsCss = `.post-container.hidden, .catalog-tile.hidden { visibility: hidden;margin-top: -1.5em;height: 0; }`;
const hideThumbnailsCss = `.file-thumb, .catalog-thumb { visibility: hidden !important; }`;
const hideRecursiveCss = `.op.hidden ~ .anchor, .op.hidden ~ .post-container { display: none; }`;
const heightUnlimitCss = `img, video { max-height: unset; }`;
const crispCss = `img { image-rendering: crisp-edges; }`;
const nonColorIdsCss = `.user-id { background: transparent none repeat scroll 0% 0% !important; border-color: transparent; text-shadow: none; color: var(--font-color); }`;
const alwaysShowSpoilersCss = `.spoiler { color: var(--font-color) !important; background: transparent none repeat scroll 0% 0%; outline: 1px solid black; cursor: auto; }`;
const smoothScrollingCss = `html { scroll-behavior: smooth; }`;
//make classes with css
new CssToggle('hiderecursive-setting', 'hiderecursive', settings.hideRecursive, hideRecursiveCss);
new CssToggle('heightlimit-setting', 'heightlimit', settings.heightUnlimit, heightUnlimitCss);
new CssToggle('crispimages-setting', 'crispimages', settings.crispImages, crispCss);
new CssToggle('hidethumbnails-setting', 'hidethumbnails', settings.hideThumbnails, hideThumbnailsCss);
new CssToggle('noncolorids-setting', 'noncolorids', settings.nonColorIds, nonColorIdsCss);
new CssToggle('alwaysshowspoilers-setting', 'alwaysshowspoilers', settings.alwaysShowSpoilers, alwaysShowSpoilersCss);
new CssToggle('hidepoststubs-setting', 'hidepoststubs', settings.hidePostStubs, hidePostStubsCss);
new CssToggle('smoothscrolling-setting', 'smoothscrolling', settings.smoothScrolling, smoothScrollingCss);
window.addEventListener('addPost', function(e) {
const post = e.detail.post;
const { board, postId, userId } = post.dataset;
const hiddenKey = `${board}-${postId}`;
if (hidden.has(hiddenKey) || hidden.has(userId)) {
post.classList.add('hidden');
}
const menu = post.querySelector('.postmenu');
for (let i = 0; i < menu.children.length; i++) {
menu.children[i].originalText = menu.children[i].innerText;
}
menu.value = '';
menu.addEventListener('change', changeOption, false);
});
window.addEventListener('settingsReady', function(e) {
hidePostsList = document.getElementById('hiddenpostslist-setting');
hidePostsList.value = [...hidden];
const hidePostsListClearButton = document.getElementById('hiddenpostslist-clear');
const clearhidePostsList = () => {
setHidden(getHiddenElems(), false);
hidden = new Set();
hidePostsList.value = '';
setLocalStorage('hidden', '[]');
console.log('cleared hidden posts');
}
hidePostsListClearButton.addEventListener('click', clearhidePostsList, false);
});

@ -190,7 +190,7 @@ window.addEventListener('settingsReady', function(e) {
const clearHoverCacheList = () => {
deleteStartsWith('hovercache');
hoverCacheList.value = '';
console.log('cleared hover cache');
console.log('cleared cache');
}
hoverCacheListClearButton.addEventListener('click', clearHoverCacheList, false);
});

@ -1,4 +1,3 @@
const isCatalog = window.location.pathname.endsWith('catalog.html');
const isThread = /\/\w+\/thread\/\d+.html/.test(window.location.pathname);
const isModView = /\/\w+\/manage\/(thread\/)?(index|\d+).html/.test(window.location.pathname);
@ -18,9 +17,9 @@ function appendLocalStorageArray(key, value) {
storedArray.push(value);
setLocalStorage(key, JSON.stringify(storedArray));
}
function deleteStartsWith(startString = 'hovercache') {
//clears hover cache when localstorage gets full
function deleteStartsWith(startString='hovercache') {
//clears cache when localstorage gets full
const hoverCaches = Object.keys(localStorage).filter(k => k.startsWith(startString));
for(let i = 0; i < hoverCaches.length; i++) {
localStorage.removeItem(hoverCaches[i]);
@ -48,7 +47,7 @@ setDefaultLocalStorage('yous-setting', settings.showYous);
setDefaultLocalStorage('dragtop', null);
setDefaultLocalStorage('dragleft', null);
setDefaultLocalStorage('hidden', '[]');
setDefaultLocalStorage('filters', '{"hiddenSingle":[],"filteredId":[],"filteredName":[],"filteredTripcode":[]}');
setDefaultLocalStorage('yous', '[]');
setDefaultLocalStorage('name', '');
setDefaultLocalStorage('theme', 'default');

@ -270,7 +270,7 @@ const settings = ${JSON.stringify(configs.frontendScriptDefault)};
`${paths.scripts.src}/forms.js`,
`${paths.scripts.src}/*.js`,
`!${paths.scripts.src}/dragable.js`,
`!${paths.scripts.src}/hide.js`,
`!${paths.scripts.src}/filters.js`,
`!${paths.scripts.src}/yous.js`,
`!${paths.scripts.src}/catalog.js`,
`!${paths.scripts.src}/time.js`,
@ -278,17 +278,17 @@ const settings = ${JSON.stringify(configs.frontendScriptDefault)};
`!${paths.scripts.src}/timezone.js`,
])
.pipe(concat('all.js'))
.pipe(uglify({compress:false}))
// .pipe(uglify({compress:false}))
.pipe(gulp.dest(paths.scripts.dest));
return gulp.src([
`${paths.scripts.src}/dragable.js`,
`${paths.scripts.src}/yous.js`,
`${paths.scripts.src}/hide.js`,
`${paths.scripts.src}/filters.js`,
`${paths.scripts.src}/catalog.js`,
`${paths.scripts.src}/time.js`,
])
.pipe(concat('render.js'))
.pipe(uglify({compress:false}))
// .pipe(uglify({compress:false}))
.pipe(gulp.dest(paths.scripts.dest));
}

@ -1,7 +1,7 @@
include ./report.pug
mixin post(post, truncate, manage=false, globalmanage=false, ban=false)
.anchor(id=post.postId)
div(class=`post-container ${post.thread || ban === true ? '' : 'op'}` data-board=post.board data-post-id=post.postId data-user-id=post.userId)
div(class=`post-container ${post.thread || ban === true ? '' : 'op'}` data-board=post.board data-post-id=post.postId data-user-id=post.userId data-name=post.name data-tripcode=post.tripcode)
- const postURL = `/${post.board}/${(modview || manage || globalmanage) ? 'manage/' : ''}thread/${post.thread || post.postId}.html`;
.post-info
span
@ -54,9 +54,13 @@ mixin post(post, truncate, manage=false, globalmanage=false, ban=false)
span.noselect: a(href=`${postURL}#postform`) [Reply]
|
select.jsonly.postmenu
option Hide
option(value='hide') Hide
if post.userId
option Hide by ID
option(value='id') Filter ID
if post.name
option(value='name') Filter Name
if post.tripcode
option(value='tripcode') Filter Tripcode
.post-data
if post.files.length > 0
.post-files(class=(post.files.length > 1 ? 'fn' : ''))

Loading…
Cancel
Save