More fleshed out filters, with a special section in settings, support regex and subject reference #244

merge-requests/208/head
Thomas Lynch 4 years ago
parent f9e15e23e8
commit d31a33e7e3
  1. 114
      gulp/res/js/filters.js
  2. 2
      gulp/res/js/localstorage.js
  3. 11
      gulp/res/js/pugfilters.js
  4. 16
      views/mixins/filters.pug
  5. 31
      views/mixins/modal.pug
  6. 4
      views/mixins/post.pug

@ -1,52 +1,64 @@
const getFiltersFromLocalStorage = () => {
const savedFilters = JSON.parse(localStorage.getItem('filters'));
/* i havent actually checked if the serialization overhead is worth the improvement in filter speed, i only assumed.
So if it turns out this is slower, i'd accept a PR to change it :^) */
const savedFilters = JSON.parse(localStorage.getItem('filters1'));
return savedFilters.reduce((acc, filter) => {
acc[filter.type].add(filter.type.endsWith('r') ? new RegExp(filter.val) : filter.val);
const regexFilter = filter.type.endsWith('r');
if (regexFilter) {
acc[filter.type].push(new RegExp(filter.val, 'i')); //todo: serialize flags? probs not necessary
} else {
acc[filter.type].add(filter.val);
}
return acc;
}, {
single: new Set(),
fid: new Set(),
fname: new Set(),
fsub: new Set(),
ftrip: new Set(),
fnamer: new Set(),
ftripr: new Set(),
fnamer: [],
ftripr: [],
fsubr: [],
});
};
let { single, fid, fname, ftrip, fnamer, ftripr } = getFiltersFromLocalStorage();
let { single, fid, fname, ftrip, fsub, fnamer, ftripr, fsubr } = getFiltersFromLocalStorage();
let filtersTable;
const updateFiltersTable = () => {
[...filtersTable.children].slice(2).forEach(row => row.remove());
filtersTable.insertAdjacentHTML('beforeend', filters({filterArr: JSON.parse(localStorage.getItem('filters'))}))
[...filtersTable.children].slice(3).forEach(row => row.remove());
filtersTable.insertAdjacentHTML('beforeend', filters({filterArr: JSON.parse(localStorage.getItem('filters1'))}))
const closeButtons = filtersTable.querySelectorAll('.close');
for (let elem of closeButtons) {
const { type: closeType, data: closeData } = elem.dataset;
let { type: closeType, data: closeData } = elem.dataset;
if (closeType.endsWith('r')) {
closeData = new RegExp(closeData, 'i');
}
elem.addEventListener('click', () => { toggleFilter(closeType, closeData) });
}
}
const updateSavedFilters = () => {
setLocalStorage('filters', JSON.stringify([
setLocalStorage('filters1', JSON.stringify([
...([...single].map(x => ({type:'single', val:x}))),
...([...fid].map(x => ({type:'fid', val:x}))),
...([...ftrip].map(x => ({type:'ftrip', val:x}))),
...([...fname].map(x => ({type:'fname', val:x}))),
...([...fnamer].map(x => ({type:'fnamer', val:x.source.toString()}))),
...([...ftripr].map(x => ({type:'ftripr', val:x.source.toString()}))),
...([...fsub].map(x => ({type:'fsub', val:x}))),
...fnamer.map(x => ({type:'fnamer', val:x.source.toString()})),
...ftripr.map(x => ({type:'ftripr', val:x.source.toString()})),
...fsubr.map(x => ({type:'fsubr', val:x.source.toString()})),
]));
updateFiltersTable();
};
const anyFilterMatches = (filteringPost) => {
const { board, postId, userId, name, tripcode } = filteringPost.dataset;
const { board, postId, userId, name, subject, tripcode } = filteringPost.dataset;
return fid.has(userId)
|| fname.has(name)
|| ftrip.has(tripcode)
// || fnamer.some(r => r.test(name))
// || ftripr.some(r => r.test(tripcode))
|| fsub.has(tripcode)
|| fnamer.some(r => r.test(name))
|| ftripr.some(r => r.test(tripcode))
|| fsubr.some(r => r.test(subject))
}
const togglePostsHidden = (posts, state) => {
@ -63,8 +75,8 @@ const togglePostsHidden = (posts, state) => {
const getPostsByRegex = (attribute, regex) => {
const matches = [];
for (let elem of document.querySelectorAll(`[${attribute}]`)) {
const value = element.getAttribute(attribute).toString();
if (regex.test(value)) {
const value = elem.getAttribute(attribute).toString();
if (regex.test(value) === true) {
matches.push(elem);
}
}
@ -94,6 +106,12 @@ const getPostsByFilter = (type, data) => {
case 'ftripr':
posts = getPostsByRegex('data-tripcode', data);
break;
case 'fsub':
posts = document.querySelectorAll(`[data-subject="${CSS.escape(data)}"]`);
break;
case 'fsubr':
posts = getPostsByRegex('data-subject', data);
break;
default:
break;
}
@ -113,13 +131,28 @@ const setFilterState = (type, data, state) => {
fname[addOrDelete](data);
break;
case 'fnamer':
fnamer[addOrDelete](data.source.toString());
fnamer = fnamer.filter(r => r.source != data.source);
if (state) {
fnamer.push(data);
}
break;
case 'ftrip':
ftrip[addOrDelete](data);
break;
case 'ftripr':
ftripr[addOrDelete](data.source.toString());
ftripr = ftripr.filter(r => r.source != data.source);
if (state) {
ftripr.push(data);
}
break;
case 'fsub':
fsub[addOrDelete](data);
break;
case 'fsubr':
fsubr = fsubr.filter(r => r.source != data.source);
if (state) {
fsubr.push(data);
}
break;
default:
break;
@ -127,9 +160,7 @@ const setFilterState = (type, data, state) => {
};
const toggleFilter = (filterType, filterData, state) => {
//console.log('filtering', filterType, filterData, state);
const posts = getPostsByFilter(filterType, filterData);
if (posts.length === 0) { return; }
setFilterState(filterType, filterData, state);
togglePostsHidden(posts, state);
updateSavedFilters();
@ -151,6 +182,9 @@ const postMenuChange = function(e) {
case 'fname':
filterData = postDataset.name;
break;
case 'fsub':
filterData = postDataset.subject;
break;
}
toggleFilter(filterType, filterData, hiding);
this.value = '';
@ -172,17 +206,21 @@ const getHiddenElems = () => {
for (let name of fname) {
posts = posts.concat(getPostsByFilter('fname', name));
}
for (let subject of fsub) {
posts = posts.concat(getPostsByFilter('fsub', subject));
}
for (let tripcode of ftrip) {
posts = posts.concat(getPostsByFilter('ftrip', tripcode));
}
// for (let namer of fnamer) {
// posts = posts.concat(getPostsByFilter('fname', namer));
// }
// for (let tripcoder of ftripr) {
// posts = posts.concat(getPostsByFilter('ftrip', tripcoder));
// }
for (let namer of fnamer) {
posts = posts.concat(getPostsByFilter('fnamer', namer));
}
for (let tripcoder of ftripr) {
posts = posts.concat(getPostsByFilter('ftripr', tripcoder));
}
for (let subr of fsubr) {
posts = posts.concat(getPostsByFilter('fsubr', subr));
}
return posts;
};
@ -203,14 +241,26 @@ window.addEventListener('settingsReady', function(e) {
filtersTable = document.getElementById('advancedfilters');
updateFiltersTable();
const filtersForm = document.getElementById('filter-form');
filtersForm.addEventListener('submit', (e) => {
e.preventDefault();
const isRegex = filtersForm.elements.regex.checked;
const type = `${filtersForm.elements.type.value}${isRegex ? 'r' : ''}`;
const val = isRegex ? new RegExp(filtersForm.elements.value.value, 'i') : filtersForm.elements.value.value;
console.log('adding filter', type, val);
toggleFilter(type, val, true);
})
const filterClearButton = document.getElementById('filters-clear');
const clearFilters = () => {
single = new Set(),
fid = new Set(),
fname = new Set(),
fsub = new Set(),
ftrip = new Set(),
fnamer = new Set(),
ftripr = new Set(),
fnamer = [],
ftripr = [],
fsubr = [],
updateFiltersTable();
togglePostsHidden(document.querySelectorAll('.post-container'), false);
updateSavedFilters();

@ -48,7 +48,7 @@ setDefaultLocalStorage('yous-setting', settings.showYous);
setDefaultLocalStorage('dragtop', null);
setDefaultLocalStorage('dragleft', null);
setDefaultLocalStorage('filters', '[]');
setDefaultLocalStorage('filters1', '[]');
setDefaultLocalStorage('yous', '[]');
setDefaultLocalStorage('name', '');
setDefaultLocalStorage('theme', 'default');

@ -6,25 +6,30 @@ var pug_match_html=/["&<>]/;function filters(locals) {var pug_html = "", pug_mix
(function (filterArr) {
pug_mixins["filters"] = pug_interp = function(filterArr){
var block = (this && this.block), attributes = (this && this.attributes) || {};
const filterTypeMap = { single: 'single', fid: 'ID', fname: 'name', ftrip: 'tripcode', fnamer: 'name regex', ftripr: 'tripcode regex' }
const filterTypeMap = { single: 'Single', fid: 'ID', fname: 'Name', ftrip: 'Tripcode', fnamer: 'Name', ftripr: 'Tripcode', fsub: 'Subject', fsubr: 'Subject' }
if (filterArr.length > 0) {
// iterate filterArr
;(function(){
var $$obj = filterArr;
if ('number' == typeof $$obj.length) {
for (var pug_index0 = 0, $$l = $$obj.length; pug_index0 < $$l; pug_index0++) {
var filter = $$obj[pug_index0];
pug_html = pug_html + "\u003Ctr\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filterTypeMap[filter.type]) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filter.val.toString()) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E\u003Ca" + (" class=\"close\""+pug_attr("data-type", filter.type, true, false)+pug_attr("data-data", filter.val, true, false)) + "\u003EX\u003C\u002Fa\u003E\u003C\u002Ftd\u003E\u003C\u002Ftr\u003E";
pug_html = pug_html + "\u003Ctr\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filterTypeMap[filter.type]) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filter.val.toString()) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E\u003Cinput" + (pug_attr("disabled", true, true, false)+" type=\"checkbox\""+pug_attr("checked", filter.type.endsWith('r'), true, false)) + "\u002F\u003E\u003C\u002Ftd\u003E\u003Ctd\u003E\u003Ca" + (" class=\"right close\""+pug_attr("data-type", filter.type, true, false)+pug_attr("data-data", filter.val, true, false)) + "\u003EX\u003C\u002Fa\u003E\u003C\u002Ftd\u003E\u003C\u002Ftr\u003E";
}
} else {
var $$l = 0;
for (var pug_index0 in $$obj) {
$$l++;
var filter = $$obj[pug_index0];
pug_html = pug_html + "\u003Ctr\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filterTypeMap[filter.type]) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filter.val.toString()) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E\u003Ca" + (" class=\"close\""+pug_attr("data-type", filter.type, true, false)+pug_attr("data-data", filter.val, true, false)) + "\u003EX\u003C\u002Fa\u003E\u003C\u002Ftd\u003E\u003C\u002Ftr\u003E";
pug_html = pug_html + "\u003Ctr\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filterTypeMap[filter.type]) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E" + (pug_escape(null == (pug_interp = filter.val.toString()) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\u003Ctd\u003E\u003Cinput" + (pug_attr("disabled", true, true, false)+" type=\"checkbox\""+pug_attr("checked", filter.type.endsWith('r'), true, false)) + "\u002F\u003E\u003C\u002Ftd\u003E\u003Ctd\u003E\u003Ca" + (" class=\"right close\""+pug_attr("data-type", filter.type, true, false)+pug_attr("data-data", filter.val, true, false)) + "\u003EX\u003C\u002Fa\u003E\u003C\u002Ftd\u003E\u003C\u002Ftr\u003E";
}
}
}).call(this);
}
else {
pug_html = pug_html + "\u003Ctd colspan=\"4\"\u003ENo Filters\u003C\u002Ftd\u003E";
}
};
pug_mixins["filters"](filterArr);
}.call(this, "filterArr" in locals_for_with ?

@ -1,7 +1,11 @@
mixin filters(filterArr)
- const filterTypeMap = { single: 'single', fid: 'ID', fname: 'name', ftrip: 'tripcode', fnamer: 'name regex', ftripr: 'tripcode regex' }
each filter in filterArr
tr
td #{filterTypeMap[filter.type]}
td #{filter.val.toString()}
td: a.close(data-type=filter.type data-data=filter.val) X
- const filterTypeMap = { single: 'Single', fid: 'ID', fname: 'Name', ftrip: 'Tripcode', fnamer: 'Name', ftripr: 'Tripcode', fsub: 'Subject', fsubr: 'Subject' }
if filterArr.length > 0
each filter in filterArr
tr
td #{filterTypeMap[filter.type]}
td #{filter.val.toString()}
td: input(disabled type='checkbox' checked=filter.type.endsWith('r'))
td: a.right.close(data-type=filter.type data-data=filter.val) X
else
td(colspan=4) No Filters

@ -140,11 +140,26 @@ mixin modal(data)
textarea#customcss-setting(rows=7)
.row
.table-container.text-center
table
tbody#advancedfilters
tr
th(colspan=3) Filters
tr
th Type
th Value
th: input.right#filters-clear(type='button' value='Clear')
form#filter-form
table
tbody#advancedfilters
tr
th Post Filters
th
th
th
tr
td Type
td Value
td Regex?
td: input.right#filters-clear(type='button' value='Clear')
tr
td: select(name='type')
option(value='fname') Name
option(value='ftrip') Tripcode
option(value='fsub') Subject
td
input#filter-value-input(required type='text' name='value')
td
input(type='checkbox' name='regex')
td: input.right(type='submit' value='Add')

@ -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 data-name=post.name data-tripcode=post.tripcode)
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 data-subject=post.subject)
- const postURL = `/${post.board}/${(modview || manage || globalmanage) ? 'manage/' : ''}thread/${post.thread || post.postId}.html`;
.post-info
span
@ -59,6 +59,8 @@ mixin post(post, truncate, manage=false, globalmanage=false, ban=false)
option(value='fid') Filter ID
if post.name
option(value='fname') Filter Name
if post.subject
option(value='fsub') Filter Subject
if post.tripcode
option(value='ftrip') Filter Tripcode
.post-data

Loading…
Cancel
Save