diff --git a/deno.json b/deno.json
index 0aa7a86..bcc8c8e 100644
--- a/deno.json
+++ b/deno.json
@@ -1,7 +1,7 @@
{
"tasks": {
"dev": "deno run -A --node-modules-dir npm:vite build --watch",
- "build": "deno run -A --node-modules-dir npm:vite build --mode production",
+ "build": "deno run -A --node-modules-dir npm:vite build --mode prod",
"preview": "deno run -A --node-modules-dir npm:vite preview",
"serve": "deno run --allow-net --allow-read jsr:@std/http@1/file-server dist/"
},
diff --git a/src/ArtistFilter.ts b/src/ArtistFilter.ts
new file mode 100644
index 0000000..c445d60
--- /dev/null
+++ b/src/ArtistFilter.ts
@@ -0,0 +1,4 @@
+export type Artist = {
+ name: string,
+ userid: string
+}
\ No newline at end of file
diff --git a/src/main.ts b/src/main.ts
index 9ec8d48..2024e7a 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,12 +1,11 @@
import type { AjaxSearchResponse } from './AjaxSearchResponse.ts';
+import type { Artist } from './ArtistFilter.ts';
+
+import { TrashIcon } from './trashIcon.ts';
+
const { fetch: originalFetch } = unsafeWindow;
-type Artist = {
- name: string,
- userid: string
-}
-
-let ArtistIdList: Artist[] = loadArtistList()
+let ArtistIdList: string[] = artist_list_load().map(x => x.userid)
unsafeWindow.fetch = async (...args) => {
const [resource, config] = args;
@@ -14,7 +13,7 @@ unsafeWindow.fetch = async (...args) => {
const path : string = resource;
- if ( path.startsWith('/ajax/search') ) {
+ if ( path.startsWith('/ajax/search/') ) {
// tampering search results with artist filter
const json = () =>
response
@@ -23,15 +22,14 @@ unsafeWindow.fetch = async (...args) => {
.then((data:AjaxSearchResponse) => {
console.debug({
request: resource,
- response: data
+ response: data,
+ ArtistIdList
})
- // test filter artist id 106029976
-
if (path.startsWith('/ajax/search/illustrations')) {
data.body.illust.data = data.body.illust.data.filter( ({userId}) => !ArtistIdList.includes(userId) );
}
- else if ( path.startsWith('/ajax/search/top')) {
+ else if ( path.startsWith('/ajax/search/top') || path.startsWith('/ajax/search/artworks')) {
data.body.illustManga.data = data.body.illustManga.data.filter( ({userId}) => !ArtistIdList.includes(userId) );
}
@@ -43,12 +41,140 @@ unsafeWindow.fetch = async (...args) => {
return response;
};
-
-function loadArtistList() {
+function artist_list_load() : Artist[] {
return JSON.parse( GM_getValue('ArtistList', '[]') );
}
+function artist_list_update(list: Artist[]) {
+ GM_setValue('ArtistList', JSON.stringify(list));
+ ArtistIdList = artist_list_load().map(x => x.userid)
+}
+
+function addArtist(name:string,id:string) {
+ const list = artist_list_load();
+ if ( list.findIndex( x=> x.userid === id ) === -1) {
+ list.push({name,userid:id})
+ artist_list_update(list);
+ }
+ console.debug({name,id, list: artist_list_load()})
+}
+
+function delArtist(userid:string) {
+ const list = artist_list_load().filter( x => x.userid !== userid );
+ artist_list_update(list);
+}
+
function AttachSettings(NavNode:HTMLElement) {
+ if ( NavNode.pxv_settings_but ) return;
+
+ NavNode.pxv_settings_but = true
+
+ const button = document.createElement('button');
+
+ button.id = 'pxv-artist-filter';
+ button.classList.add('pxv-but','pxv-settings-but');
+ button.textContent = 'Artist Filter';
+
+
+ const FilterListElement = () => {
+ const template = document.createElement('template');
+
+ let list: Artist[] = artist_list_load();
+ //list = list.concat(list).concat(list).concat(list);
+
+ const el_list: Element[] = [];
+
+ for ( const { name, userid } of list) {
+
+ const item = document.createElement('div');
+
+ const artist_name = document.createElement('a');
+ artist_name.target = '_blank'
+ artist_name.href = `/users/${userid}`
+ artist_name.text = name;
+
+ const del_but = document.createElement('button');
+ del_but.innerHTML = TrashIcon;
+ del_but.onclick = () => {
+ delArtist(userid);
+ item.parentNode?.removeChild(item);
+ }
+
+ item.append(del_but,artist_name);
+ el_list.push(item);
+ }
+
+ template.append(...el_list);
+ console.debug({template})
+ return template.childNodes;
+ }
+
+ button.onclick = () => {
+ button.blur();
+
+ const template = document.createElement('template');
+ template.innerHTML = `
+
+
+
+ `;
+
+ const node = template.content.firstElementChild;
+
+ const grid = node?.getElementsByClassName('pxv-artist-grid').item(0) as HTMLDivElement;
+ grid.replaceChildren(...FilterListElement())
+
+ const submit = node?.getElementsByClassName('pxv-but').item(0) as HTMLButtonElement;
+ submit.onclick = () => document.body.removeChild(node);
+
+ document.body.appendChild(node);
+ }
+ NavNode.parentNode.insertBefore(button,NavNode.nextSibling);
+}
+
+function AttachFilterButton(ModalNode:Node) {
+ if ( ModalNode.pxv_fil_but ) return ;
+ ModalNode.pxv_fil_but = true;
+
+ const info = ModalNode.parentElement?.querySelector('div a[data-gtm-value]:not(:has(*))') as HTMLAnchorElement;
+
+ console.debug({
+ name: info.text,
+ userid: info.getAttribute('data-gtm-value')
+ })
+
+ const button = document.createElement('button');
+
+ button.id = 'pxv-artist-filter';
+ button.classList.add('pxv-but','pxv-modal-filter-but');
+ button.textContent = 'Filter';
+ button.onclick = () => {
+ if ( confirm(`Do you want to filter ${info.text}'s posts ?`)) {
+ const name = info.text;
+ const userid = info.getAttribute('data-gtm-value') || '-1';
+ addArtist(name,userid);
+ alert(`${info.text} has been added to the filter list.`);
+ }
+ }
+
+ ModalNode.appendChild(button);
+ console.debug({ModalNode})
+}
+
+function init() {
+
GM_addStyle(`
.pxv-but {
color: rgb(245, 245, 245);
@@ -62,10 +188,16 @@ function AttachSettings(NavNode:HTMLElement) {
font-weight: bold;
cursor: pointer;
}
- .artist-filter-but {
+
+ .pxv-settings-but {
margin-left: auto;
margin-right: 12px;
}
+
+ .pxv-modal-filter-but {
+ margin: 5px auto;
+ padding: 5px 24px;
+ }
.pxv-but:focus {
outline:none;
@@ -92,56 +224,70 @@ function AttachSettings(NavNode:HTMLElement) {
width: 400px;
height: 400px;
background-color: rgb(31, 31, 31);
+ display:flex;
+ flex-direction: column;
+ }
+
+ .pxv-dialog .pxv-but {
+ display: block;
+ margin: 10px auto;
}
.pxv-title {
font-size: 16px;
text-align: center;
}
+
+ .pxv-artist-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ max-height: 310px;
+ overflow-y: scroll;
+ margin-bottom: auto;
+ }
+ .pxv-artist-grid > div {
+ padding:10px 0;
+ font-size: 14px;
+ transition: background-color 0.2s;
+ display:flex;
+ }
+
+ .pxv-artist-grid > div:hover {
+ background-color: #3a3a3a;
+ }
+
+ .pxv-artist-grid > div > button {
+ margin: 0 5px;
+ padding: 0px;
+ border: medium;
+ outline: none;
+ background: transparent;
+ cursor: pointer;
+ color: rgb(133, 133, 133);
+ }
+
+ .pxv-artist-grid > div > a {
+ flex-grow:1;
+ margin: auto 0;
+ }
`)
- const button = document.createElement('button');
-
- button.id = 'pxv-artist-filter';
- button.classList.add('pxv-but','artist-filter-but');
- button.textContent = 'Artist Filter';
-
- button.onclick = () => {
- button.blur();
- const template = document.createElement('template');
- template.innerHTML = `
-
-
-
- `;
- const node = template.content.firstElementChild;
-
- const submit = node.getElementsByTagName('button').item(0);
- submit.onclick = () => document.body.removeChild(node);
-
-
- document.body.appendChild(node);
- }
- NavNode.parentNode.insertBefore(button,NavNode.nextSibling);
-}
-
-function init() {
-
- const pixivgohomeyoudrunk = setInterval(() => {
+ const attach_settings = setInterval(() => {
const navNode = document.getElementsByTagName('nav').item(0);
if (navNode){
- clearInterval(pixivgohomeyoudrunk);
AttachSettings(navNode)
}
},1000)
+
+ const pixiv_attach_artist = setInterval( () => {
+ const profileModalsearch = document.evaluate("//*/div[@open='']", document,null, XPathResult.FIRST_ORDERED_NODE_TYPE);
+ //const profileModalsearch = document.evaluate("//*/a[contains(text(),'View Profile')]", document,null, XPathResult.FIRST_ORDERED_NODE_TYPE);
+ if ( profileModalsearch.singleNodeValue ) {
+ AttachFilterButton(profileModalsearch.singleNodeValue)
+ }
+ },1000)
}
-init()
-
+init()
\ No newline at end of file
diff --git a/src/trashIcon.ts b/src/trashIcon.ts
new file mode 100644
index 0000000..7ed9da3
--- /dev/null
+++ b/src/trashIcon.ts
@@ -0,0 +1,3 @@
+export const TrashIcon = ``
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 660b856..af2d9ee 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -3,7 +3,13 @@ import Userscript from 'vite-userscript-plugin'
import { name, description, version } from './package.json';
// https://vite.dev/config/
-export default defineConfig({
+export default defineConfig( ({mode}) => {
+
+ return {
+ esbuild: {
+ pure: mode === 'prod' ? ['console.debug'] : [],
+ drop: mode === 'prod' ? ['console'] : []
+ },
plugins: [
Userscript({
entry: 'src/main.ts',
@@ -14,12 +20,13 @@ export default defineConfig({
namespace: 'noproompter',
match: 'https://www.pixiv.net/*/tags/*',
noframes:true,
- "run-at": "document-end",
+ "run-at": "document-start",
grant: ['GM.setValue', 'GM.addStyle', 'GM.getValue', 'GM.addElement']
},
server: {
port: 3000
}
})
- ],
+ ]
+ }
})