From 525b68a5d9fb716bfa3266301f31848f0c8070c5 Mon Sep 17 00:00:00 2001 From: ALewdDev <65409270+ALewdDev@users.noreply.github.com> Date: Mon, 26 Jul 2021 06:42:07 -0600 Subject: [PATCH] 2.0.5 - SockKeeper Check the changelog. --- source/manifest.json | 24 ++- source/resource/css/Dynamic.css | 130 +++++++++++- source/resource/css/Hexagons.css | 1 + source/resource/css/Theme.css | 114 +++++++++-- source/resource/icons/3QKCEKJD04.png | Bin 0 -> 593 bytes source/resource/icons/AJS1T82DLX.png | Bin 0 -> 442 bytes source/resource/icons/MNM1T9UJLX.png | Bin 0 -> 369 bytes source/resource/icons/NVTR1LKIZD.png | Bin 0 -> 594 bytes source/source/Background.js | 8 +- source/source/background/Settings.js | 2 + source/source/content/Page.js | 24 ++- source/source/content/PageFiller.js | 2 +- source/source/content/elements/Search.js | 190 ++++++++++++------ .../source/content/elements/SearchOptions.js | 2 +- .../source/content/elements/SearchRating.js | 105 ++++++++++ .../content/elements/SearchSuggestion.js | 6 +- source/source/content/mechanics/Advanced.js | 45 +++++ source/source/content/templates/Posts.js | 73 +++++-- source/source/content/utils/Settings.js | 42 ++-- source/source/library/Manifest.js | 2 + source/source/library/Readify.js | 32 +++ source/source/library/TagName.js | 4 +- source/source/library/overrides/Element.js | 35 ++++ .../source/library/overrides/EventTarget.js | 32 +++ source/source/library/overrides/Node.js | 35 ++++ source/source/library/overrides/String.js | 29 +++ 26 files changed, 805 insertions(+), 132 deletions(-) create mode 100644 source/resource/icons/3QKCEKJD04.png create mode 100644 source/resource/icons/AJS1T82DLX.png create mode 100644 source/resource/icons/MNM1T9UJLX.png create mode 100644 source/resource/icons/NVTR1LKIZD.png create mode 100644 source/source/content/elements/SearchRating.js create mode 100644 source/source/content/mechanics/Advanced.js create mode 100644 source/source/library/Readify.js create mode 100644 source/source/library/overrides/Element.js create mode 100644 source/source/library/overrides/EventTarget.js create mode 100644 source/source/library/overrides/Node.js create mode 100644 source/source/library/overrides/String.js diff --git a/source/manifest.json b/source/manifest.json index 01c9a78..daca392 100644 --- a/source/manifest.json +++ b/source/manifest.json @@ -1,14 +1,15 @@ { "name": "Neko", "short_name": "猫", - "version": "2.0.4", - "version_name": "CrackJack", + "version": "2.0.5", + "version_name": "SockKeeper", "author": "LewdTechnologies", "description": "Neko redesigns E621's interface.", "homepage_url": "https://github.com/LewdTechnologies/Neko", "permissions": [ + "background", "activeTab", "storage", @@ -20,11 +21,13 @@ "https://e621.net/*", "https://ads.dragonfru.it/*", "https://mc.yandex.ru/*" + ], "background": { "persistent": true, "scripts": [ + "source/library/Functions.js", "source/library/Debug.js", "source/library/Logger.js", @@ -43,6 +46,7 @@ "source/background/extractors/Tag.js", "source/Background.js" + ] }, @@ -60,18 +64,28 @@ "run_at": "document_start", "matches": [ "https://e621.net/posts" , "https://e621.net/posts?*" ], "js": [ + "source/content/templates/Posts.js", "source/content/utils/Settings.js", "source/content/elements/Search.js", "source/content/elements/SearchSuggestion.js", "source/content/elements/SearchOptions.js", + "source/content/elements/SearchRating.js", "source/content/mechanics/TagManager.js", + "source/content/mechanics/Advanced.js", "source/library/TagName.js" + ] },{ "run_at": "document_start", "matches": [ "https://e621.net/posts" , "https://e621.net/posts?*" ], "js": [ + + "source/library/overrides/Node.js", + "source/library/overrides/Element.js", + "source/library/overrides/String.js", + "source/library/overrides/EventTarget.js", + "source/library/Readify.js", "source/library/Functions.js", "source/content/Template.js", "source/library/Debug.js", @@ -80,6 +94,7 @@ "source/content/Page.js", "source/content/User.js", "source/library/Manifest.js" + ], "css": [ "resource/css/Hexagons.css", @@ -88,6 +103,9 @@ },{ "run_at": "document_end", "matches": [ "https://e621.net/posts" , "https://e621.net/posts?*" ], - "js": [ "source/content/PageFiller.js" ] + "js": [ + "source/content/PageFiller.js" + + ] }] } diff --git a/source/resource/css/Dynamic.css b/source/resource/css/Dynamic.css index 7eb2f8e..79ee523 100644 --- a/source/resource/css/Dynamic.css +++ b/source/resource/css/Dynamic.css @@ -7,16 +7,101 @@ */ -middle > .hasTags { +/* + SEARCH PRESETS +*/ - border-top-right-radius: 24px; - border-bottom-right-radius: 24px; +search > presets { + + width: 100%; + + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-content: center; + justify-content: flex-start; + align-items: center; + + gap: 5px; + + padding-left: 38px; } -middle > .hasSuggestions { +search > presets > rating { - border-bottom-left-radius: 0; + display: flex; + flex-wrap: nowrap; + flex-direction: row; + align-content: center; + justify-content: center; + align-items: center; + + gap: 4px; + +} + +search > presets > rating > * { + + border: 1px dashed transparent; + border-radius: 16px; + cursor: pointer; + background-color: #00000029; + +} + +search > presets > rating img { + + width: 42px; + height: auto; + pointer-events: none; + +} + + +/* + TEMPORARY RATING SELECTED +*/ + +presets > rating.safe > safe, +presets > rating.explicit > explicit, +presets > rating.questionable > questionable { + + background-color: white; + +} + +presets > rating.safe > safe > img, +presets > rating.explicit > explicit > img, +presets > rating.questionable > questionable > img { + + filter: invert(1); + +} + + +/* + DEFAULT RATING SELECTED +*/ + +presets > rating.default_safe > safe, +presets > rating.default_explicit > explicit, +presets > rating.default_questionable > questionable { + + border-color: white; + +} + + +/* + DEFAULT & TEMPORARY DEFAULT RATING SELECTED +*/ + +presets > rating.safe.default_safe > safe, +presets > rating.explicit.default_explicit > explicit, +presets > rating.questionable.default_questionable > questionable { + + border-color: var(--font-blue); } @@ -25,7 +110,7 @@ middle > .hasSuggestions { SEARCH QUICK SETTINGS */ -middle > search > options { +search > primary > bar > options { position: absolute; height: 39px; @@ -46,10 +131,41 @@ middle > search > options { } -middle > search > options > setting { +search > primary > bar > options > setting { font-weight: bold; color: var(--font-white); cursor: pointer; } + +search.hasSuggestions:not(.hasAdvanced) { + + border-bottom-left-radius: 0; + +} + +search.hasSuggestions > primary > bar { + + border-bottom-left-radius: 0; + +} + +search.hasTags:not(.hasAdvanced) { + + border-top-right-radius: 24px; + +} + +search.hasTags { + + border-bottom-right-radius: 24px; + +} + +search.hasTags > primary > bar { + + border-top-right-radius: 24px; + border-bottom-right-radius: 24px; + +} diff --git a/source/resource/css/Hexagons.css b/source/resource/css/Hexagons.css index 4278980..5e40cf5 100644 --- a/source/resource/css/Hexagons.css +++ b/source/resource/css/Hexagons.css @@ -37,6 +37,7 @@ --font-default: 'Noto'; + --cursor-x: url('chrome-extension://__MSG_@@extension_id__/resource/icons/AJS1T82DLX.png'), auto; --background: url('data:image/png;base64,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'); diff --git a/source/resource/css/Theme.css b/source/resource/css/Theme.css index a45c857..f7d2cd6 100644 --- a/source/resource/css/Theme.css +++ b/source/resource/css/Theme.css @@ -70,6 +70,17 @@ body { } +/* + ADVANCED +*/ + +[advance]:not(.show) { + + display: none; + +} + + /* NAVIGATION */ @@ -104,6 +115,12 @@ navigation > div { } +navigation > .logIO { + + transition: .5s; + +} + /* CONTENT @@ -198,6 +215,12 @@ taglist > tag > name { } +taglist > tag > :is(name,count) { + + transition: .3s; + +} + taglist > tag.dummy > name , taglist > tag.dummy > count { @@ -226,40 +249,58 @@ taglist > tag > a { SEARCH */ -middle > search { +search { width: calc(100% - 44px); - min-height: 32px; display: flex; - flex-direction: row-reverse; + flex-direction: column; flex-wrap: nowrap; align-content: flex-start; - justify-content: flex-end; - align-items: center; + justify-content: flex-start; + align-items: stretch; margin: 0 20px; border-radius: 11px; - background-color: #010b1b; + background-color: var(--blue-dim); border: 6px solid var(--blue-dim); + gap: 5px; + } -middle > .hasTags { +search > primary { + + width: 100%; + min-height: 32px; - border-top-right-radius: 24px; - border-bottom-right-radius: 24px; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-content: center; + justify-content: flex-start; + align-items: center; } -middle > .hasSuggestions { +search > primary > bar { - border-bottom-left-radius: 0; + width: -webkit-fill-available; + + display: flex; + flex-direction: row-reverse; + flex-wrap: nowrap; + align-content: flex-start; + justify-content: flex-end; + align-items: center; + + background-color: #010b1b; + border-radius: 7px; } -middle > search > input { +search > primary > bar > input { max-width: 300px; min-width: 300px; @@ -282,14 +323,14 @@ middle > search > input { } -middle > search > input::selection { +search > primary > bar > input::selection { background-color: var(--font-light); color: var(--blue-dark); } -middle > search > tags { +search > primary > bar > tags { width: -webkit-fill-available; @@ -305,17 +346,31 @@ middle > search > tags { } -middle > search > tags > tag { +search > primary > bar > tags > tag { - padding: 3px 14px; + padding: 1px 12px; - color: var( --font-white); + color: var(--font-white); border-radius: 16px; background-color: var(--blue-dim); + border: 2px solid var(--blue-dim); + + border: 2px solid transparent; + + transition-duration: .2s; + cursor: var(--cursor-x); } -middle > search > suggestions { +search > primary > bar > tags > tag:hover { + + border-color: #ff83836b; + background-color: #844a4a; + +} + + +search > primary > bar > suggestions { position: absolute; left: -6px; @@ -339,7 +394,7 @@ middle > search > suggestions { } -middle > search > suggestions > tag { +search > primary > bar > suggestions > tag { width: -webkit-fill-available; @@ -351,12 +406,31 @@ middle > search > suggestions > tag { } -middle > search > suggestions > tag:hover { +search > primary > bar > suggestions > tag:hover { background-color: var(--blue-dim); } +search > primary > settings { + + margin-right: 5px; + +} + +search > primary > settings > img { + + width: 32px; + height: auto; + + cursor: pointer; + +} + +search > primary > settings > img:hover { + filter: drop-shadow(0px 0px 4px #000000DD); +} + /* POSTS diff --git a/source/resource/icons/3QKCEKJD04.png b/source/resource/icons/3QKCEKJD04.png new file mode 100644 index 0000000000000000000000000000000000000000..3ebd20374ad0b120ada0c53045b04c97d9e75429 GIT binary patch literal 593 zcmV-X0_zVmH`#N_m!F-DvvjI#??*M~9OOrp;>9~De)O1_F zTV^(IW_dGvV`f*(Y|6}0V?tvL8A?M6~&-yit@MQ z%>j?3p8&JcuX@(J3Yr9-skx%`B+=9P0dPGQUk{pHCwhIh0&8NP#}6{Ky)v!@hfXOhhhs^*PST9(r=nR&=F@T>v|K1=;?hJYqTD_ zJy1+O>v~fGSO^+DC3?M;rQ0lIU1w?l{XkQVZUp{@ye80}WsRu=REa)vCIW9lUNy_w f9LI4S=Re~IO+aD9YPNn$00000NkvXXu0mjfEX@Ir literal 0 HcmV?d00001 diff --git a/source/resource/icons/AJS1T82DLX.png b/source/resource/icons/AJS1T82DLX.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7a24482016cae6ce6eb16cca258be29b298dcd GIT binary patch literal 442 zcmV;r0Y(0aP)QenqRcUIn_i53|oVq;BOeE~`19Y|#G5Z3i4R%}?bVVLOyFk^xF zx|kA%!Cju5?|1IK-}x8-6H$`PBQZ1R$^pQ%+nN0iheQCxK|Y6GHU(W#Bmlw{v7jr8 z)XSzY$mf9VRuqVcjLn9YlQ9iTg~VD_>z5z^gte;HhowSdIT@3&*&I<-Me3&FXh$RH zBx6{~)8;Y6oIF42(dB95&;x)qbx}Ko%vt~h0IV(Knnm0^yQLk(TCgc_g zUj2O2gU?6I0%`J$-2MPPl|Nf9pFhdW##Ng%by4diV`xVsXh$RXdVPle|0HYwWy_57 z0d^x#003B5=GD>1TUwh<>EY2wZhwIE#hgZ^;)^zy8@795_uF>v+$BEPcnxxMN$AG1 zVY?OkxeVIT2)e1bZ65YH*hBic3;>u}5S&i(1Va=qR~jy_SG?piGaD|iR}7ac4Novc kg41c%t?|4o&PVb81Gl}N5|12O?f?J)07*qoM6N<$f?1r%!TlzGMWFCIIM|PfUflV zGvd%vsRs3wdQ}})r_~vCq{OdXy`wI;!9udNA4cw#pf0+d(GtIjg8nPD1`|8P?ov;y zJqN#%e?OWfz~bY}B2H z5wR8#Yrvyqi{!JFmV#a>m2E&oEJlP)+`bn2Ckp-ELjOxuIsFZ7bxsx$AJr+~GBBau zPtx`Dd=e3#)bqg6!qD#YJfaR3>?;xR@?f*xBWg#JBG{?Ul@!c5wKMt5m*}PJH{U92 zKvUEfU=lb3ECEx%Q(!sSCX-KX)OrPgAz%;?xDXMq0n(A5P1+DJ%;qaF3Jd_Bfolc( zN)0*hjoq$*I+pD7CF2^$eyl{BN!o|1^R4x`73S+u|9sL?zazcY`kT124Ny<213-Vl z+^Y_#{b`YJlf4JHrM9W9z|CX>cvDqQwW2;~Qn0(zf?pMEOQ|)ORkzh8^^$r+9j-d> zDvRJd;KdHwIpH~R<{n0h-Ve%xjFVh1#U*V62-s6`~Ie9 gGMP*!lgaFb-$V%ZiGSvG8~^|S07*qoM6N<$g8T*;SO5S3 literal 0 HcmV?d00001 diff --git a/source/source/Background.js b/source/source/Background.js index 16bd846..f02f552 100644 --- a/source/source/Background.js +++ b/source/source/Background.js @@ -13,8 +13,7 @@ const { onMessage } = runtime; - const - requests = {}; + const requests = {}; /* @@ -24,6 +23,9 @@ const on = (request,processor) => requests[request] = processor; + const openTab = ({ url , active }) => (resolve) => + chrome.tabs.create({ url , active },resolve); + /* LISTEN TO CONTENT SCRIPT @@ -57,6 +59,8 @@ on('user.logout',() => User.logout); + on('tabs.open',openTab); + })(); diff --git a/source/source/background/Settings.js b/source/source/background/Settings.js index 07e1300..bbd93f3 100644 --- a/source/source/background/Settings.js +++ b/source/source/background/Settings.js @@ -49,7 +49,9 @@ load().then((data = {}) => { + data['advanced_mode'] ??= true; data['search.automatic_suggestions'] ??= true; + data['search.rating'] ??= null; settings = new Map(Object.entries(data)); diff --git a/source/source/content/Page.js b/source/source/content/Page.js index f3cb27c..41d6ff5 100644 --- a/source/source/content/Page.js +++ b/source/source/content/Page.js @@ -16,6 +16,28 @@ const parameter = new URLSearchParams(search); - Page.page = parameter.get('page') ?? 0; + Page.rating = null; + + Page.page = Number(parameter.get('page') ?? 0); + + Page.tags = (parameter.get('tags') ?? '') + .toLowerCase() + .split(' ') + .map((tag) => { + return (tag.startsWith('-')) + ? [ tag.substring(1) , true ] + : [ tag , false ]; + }) + .filter(([ tag ]) => { + switch(tag){ + case 'rating:safe': + case 'rating:explicit': + case 'rating:questionable': + Page.rating = tag.substring(7); + return false; + default: + return true; + } + }); })(); diff --git a/source/source/content/PageFiller.js b/source/source/content/PageFiller.js index cb98cac..73763be 100644 --- a/source/source/content/PageFiller.js +++ b/source/source/content/PageFiller.js @@ -48,7 +48,7 @@ const toDoc = (template) => ` - E621 + Search diff --git a/source/source/content/elements/Search.js b/source/source/content/elements/Search.js index f6bf1c7..1e0e224 100644 --- a/source/source/content/elements/Search.js +++ b/source/source/content/elements/Search.js @@ -11,7 +11,7 @@ window.Search ??= {}; - let search , input , tags; + let bar , search , input , tags; let timeout; @@ -40,29 +40,33 @@ const query = [...tags.children] .map((element) => element.dataset) - .map((data) => data.id) + .map((data) => data.id); + + const { current } = SearchRating; + + if(current) + query.push(`rating:${ current }`); + + const encoded = query .map(encodeURIComponent) .join('+'); - return toSearch(query); + return toSearch(encoded); }; - const capitalize = (string) => - (string[0]?.toUpperCase() ?? '') + string.substring(1); - const refactorInput = (string) => string .split(/ +/) - .map(capitalize) + .map((string) => string.capitalize()) .join(' '); const tagFromName = (tagName) => tagName .trim() - .replace(/ +/,'_') - .replace(/_+/,'_') + .replaceAll(/ +/g,'_') + .replaceAll(/_+/g,'_') .toLowerCase(); const append = (char) => { - changeTo(input.value + char); + delete input.dataset.tag; delete input.dataset.id; @@ -74,10 +78,11 @@ suggest(); },500); } + } const backtrack = () => { - changeTo(input.value.slice(0,-1)); + delete input.dataset.tag; delete input.dataset.id; @@ -89,8 +94,43 @@ suggest(); },500); } + } + + /* + CREATE TAG LIST ITEM + */ + + const createTag = (id,name) => { + + const container = create('tag'); + + container.dataset.id = id; + container.innerText = name; + + container.addEventListener('click',(event) => { + + event.preventDefault(); + event.stopImmediatePropagation(); + + container.remove(); + + if(!tags.children.length) + search.classList.remove('hasTags'); + + }); + + tags.appendChild(container); + search.classList.add('hasTags'); + + }; + + + /* + PUSH TAG ONTO TAG LIST + */ + const pushTag = async () => { SearchSuggestion.hide(); @@ -98,8 +138,9 @@ const tag = input.value.trim(); const tagid = tagFromName(tag); + const { dataset } = input; - const valid = await TagManager.isValid(input.dataset.tag ?? tagid); + const valid = await TagManager.isValid(dataset.tag ?? tagid); if(!valid) return; @@ -110,19 +151,21 @@ return; - const container = create('tag'); + const + id = dataset.tag ?? tagid, + name = TagName.from(dataset.tag ?? tagid); - container.dataset.id = input.dataset.tag ?? tagid; - container.innerText = TagName.from(input.dataset.tag ?? tagid); + createTag(id,name); - delete input.dataset.tag; - delete input.dataset.id; + delete dataset.tag; + delete dataset.id; - tags.appendChild(container); + }; - search.classList.add('hasTags'); - }; + /* + REMOVE ALL TAGS + */ const clearTags = () => { @@ -134,6 +177,11 @@ }; + + /* + SUGGEST TAGS FOR INPUT + */ + const suggest = () => { const string = tagFromName(input.value); @@ -146,6 +194,20 @@ }; + const keys = { + 'Escape': [ true , () => SearchSuggestion.hide() ], + 'Backspace': [ false , backtrack ], + 'Tab': [ true , pushTag ], + 'Delete': [ false , ({ shiftKey }) => + shiftKey && clearTags()], + 'Enter': [ true , () => + buildQuery() + .then(redirectTo)], + 'ControlLeft': [ false , () => + Settings.not('search.automatic_suggestions') && suggest()], + 'ControlRight': [ false , () => + Settings.not('search.automatic_suggestions') && suggest()] + }; /* @@ -176,18 +238,31 @@ Search.init = () => { search = select('search'); - tags = select('search > tags'); - - input = create('input'); - input.setAttribute('spellcheck',false); - search.appendChild(input); + bar = select('search > primary > bar'); + tags = select('search > primary > bar > tags'); + input = select('search > primary > bar > input'); - search.onclick = () => + bar.onclick = () => input.focus(); onKey(window,handleFocus); - onKey(search,handleInput); + onKey(bar,handleInput); + + const settingsbutton = select('search > primary > settings > img'); + settingsbutton.addEventListener('click',(e) => { + + e.preventDefault(); + e.stopImmediatePropagation(); + + SearchOptions.toggle(); + + }); + + Page.tags.forEach(([ tag , negative ]) => { + + createTag(tag,TagName.from(tag)); + }); }; @@ -197,45 +272,27 @@ function handleInput(e){ - const action = actionFromInput(e); + const { key , code , shiftKey } = e; - if(!action) - return; - - e.stopImmediatePropagation(); - e.preventDefault(); - action(); - - }; + const consume = () => { + e.stopImmediatePropagation(); + e.preventDefault(); + }; + if(code in keys){ + const [ cancel , action ] = keys[code]; - /* - ACTION FROM INPUT - */ + if(cancel) + consume(); - function actionFromInput({ key , code , shiftKey }){ - - switch(code){ - case '': - return (key === 'Unidentified') ? () => SearchOptions.toggle() : null; - case 'Escape': - return () => SearchSuggestion.hide(); - case 'Delete': - return shiftKey && (() => clearTags()); - case 'Enter': - return () => buildQuery().then(redirectTo); - case 'Tab': - return () => pushTag(); - case 'Backspace': - return () => backtrack(); - case 'ControlLeft': - case 'ControlRight': - return () => Settings.not('search.automatic_suggestions') && suggest(); - default: - if(/^[A-z0-9_ -]$/.test(key)) - return () => append(key); + action(e); + } else + if(/^[A-z0-9_ -]$/.test(key)){ + append(key); + setTimeout(() => { + input.value = refactorInput(input.value); + },10); } - }; @@ -245,13 +302,20 @@ function handleFocus(e){ - if(e.code !== 'Tab') + if(!['Tab','F1'].includes(e.code)) return; e.stopImmediatePropagation(); e.preventDefault(); - input.focus(); + switch(e.code){ + case 'Tab': + input.focus(); + return; + case 'F1': + Advanced.toggle(); + return; + } }; diff --git a/source/source/content/elements/SearchOptions.js b/source/source/content/elements/SearchOptions.js index e5c2606..cd7bd4f 100644 --- a/source/source/content/elements/SearchOptions.js +++ b/source/source/content/elements/SearchOptions.js @@ -53,7 +53,7 @@ SearchOptions.init = () => { - menu = select('search > options'); + menu = select('search > primary > bar > options'); for(const [ key , id , txt ] of options){ diff --git a/source/source/content/elements/SearchRating.js b/source/source/content/elements/SearchRating.js new file mode 100644 index 0000000..252b00e --- /dev/null +++ b/source/source/content/elements/SearchRating.js @@ -0,0 +1,105 @@ +/* + COPYRIGHT 2021 @ LewdTechnologies + + CONTACT: + # Email: LewdTechnologies@gmail + # Website: Github.com/LewdTechnologies/Neko +*/ + + +(() => { + + window.SearchRating ??= {}; + + + let list , rating , default_rating; + + + /* + HELPER + */ + + const update = (mode) => { + + list.classList.remove(rating); + rating = mode; + + if(rating) + list.classList.add(rating); + + }; + + const updateDefault = (mode) => { + + list.classList.remove(`default_${ default_rating }`); + default_rating = mode; + + if(default_rating) + list.classList.add(`default_${ default_rating }`); + + }; + + let updateDefaultInitial = (mode) => { + + update(Page.rating ?? mode); + + (updateDefaultInitial = updateDefault)(mode); + + }; + + + SearchRating.init = () => { + + list = select('search > presets > rating'); + + list.items.forEach((element) => { + + element.preventDefaultAction('contextmenu'); + + element.addEventListener('mousedown',(event) => { + + event.preventDefault(); + event.stopImmediatePropagation(); + + const { button , target } = event; + + let mode = target.localName; + + switch(button){ + case 0: + + if(mode === rating) + mode = null; + + update(mode); + + break; + case 2: + + if(mode === default_rating) + mode = null; + + if(mode) + update(mode); + + Settings.set('search.rating',mode); + + break; + } + }); + }); + + + Settings.on('search.rating')((mode) => updateDefaultInitial(mode)); + + }; + + Object.defineProperty(SearchRating,'current',{ + get: () => rating + }); + + Object.defineProperty(SearchRating,'default',{ + get: () => default_rating + }); + +})(); diff --git a/source/source/content/elements/SearchSuggestion.js b/source/source/content/elements/SearchSuggestion.js index 0b53a28..baae1cd 100644 --- a/source/source/content/elements/SearchSuggestion.js +++ b/source/source/content/elements/SearchSuggestion.js @@ -26,7 +26,7 @@ container = select('suggestions'); search = select('search'); posts = select('posts'); - input = select('search > input'); + input = select('search > primary > bar > input'); }; @@ -67,10 +67,10 @@ }; - posts.classList.add('unfocused'); search.classList.add('hasSuggestions'); + posts.classList.add('unfocused'); container.style.visibility = 'visible'; - + }); }; diff --git a/source/source/content/mechanics/Advanced.js b/source/source/content/mechanics/Advanced.js new file mode 100644 index 0000000..bf0df1f --- /dev/null +++ b/source/source/content/mechanics/Advanced.js @@ -0,0 +1,45 @@ +/* + COPYRIGHT 2021 @ LewdTechnologies + + CONTACT: + # Email: LewdTechnologies@gmail + # Website: Github.com/LewdTechnologies/Neko +*/ + + +(() => { + + window.Advanced ??= {}; + + + /* + SETUP ADVANCED MODE + */ + + Advanced.init = () => { + + Settings.on('advanced_mode')((state) => { + + state = (state) ? 'add' : 'remove'; + + selectAll('[advanced]') + .map((element) => element.classList) + .forEach((list) => list[state]('hasAdvanced')); + + selectAll('[advance]') + .map((element) => element.classList) + .forEach((list) => list[state]('show')); + + }); + + }; + + + /* + TOGGLE ADVANCED MODE + */ + + Advanced.toggle = () => + Settings.toggle('advanced_mode'); + +})(); diff --git a/source/source/content/templates/Posts.js b/source/source/content/templates/Posts.js index aae70a4..cca222b 100644 --- a/source/source/content/templates/Posts.js +++ b/source/source/content/templates/Posts.js @@ -16,22 +16,21 @@ FurnishTemplate = (info) => { - const - { tags , posts } = info, - { floor } = Math; + { floor } = Math, + { tags , posts } = info; /* HELPER */ + const preventEvent = (e) => + e.preventDefault(); + const create = (type) => document.createElement(type); - const readify = (count) => - count < 1000 ? count : count < 1000000 ? `${ floor(count / 1000) }k` : `${ floor(count / 100000) / 10 }M`; - const redirectTo = (url) => window.location.href = url; @@ -45,7 +44,13 @@ redirectTo(toPostUrl(postId)); const openPost = (postId) => - window.open(toPostUrl(postId),'_blank'); + chrome.runtime.sendMessage({ + action: 'tabs.open', + data: { + url: toPostUrl(postId), + active: false + } + },() => {}); const tagToDisplay = (tagName) => { @@ -119,7 +124,7 @@ const tagContainer = children[index] ?? newContainer(); const [ name , count ] = tagContainer.children; - count.innerText = readify(tag.count); + count.innerText = Readify.postCount(tag.count); name.innerHTML = ''; const parts = tagToDisplay(tag.name); @@ -174,10 +179,21 @@ image.src = post.urls.preview; - image.addEventListener('mousedown',({ button }) => - (button === 0) - ? gotoPost(post.id) - : openPost(post.id)); + image.preventDefaultAction('contextmenu'); + + image.addEventListener('mousedown',(e) => { + e.preventDefault(); + e.stopImmediatePropagation(); + }); + + image.addEventListener('mouseup',(e) => { + + e.preventDefault(); + e.stopImmediatePropagation(); + + ((e.button === 0) ? gotoPost : openPost)(post.id); + + }); image.onload = () => classList.remove('dummy'); @@ -208,11 +224,13 @@ })(); + // window.preventDefaultAction('contextmenu'); Search.init(); SearchSuggestion.init(); SearchOptions.init(); - + SearchRating.init(); + Advanced.init(); window.scrollTo(0,0); @@ -341,10 +359,31 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/source/content/utils/Settings.js b/source/source/content/utils/Settings.js index 73fe9c1..e76f249 100644 --- a/source/source/content/utils/Settings.js +++ b/source/source/content/utils/Settings.js @@ -13,33 +13,48 @@ const { connect } = chrome.runtime; - const listeners = new Map; - let settings; + const + settings = new Map, + listeners = new Map; const port = connect({ name: 'settings' }); - let listener = (data = []) => { - settings = new Map(data); - - listener = ([ type , value ]) => - update(type,value); - }; - - port.onMessage.addListener((...args) => listener(...args)); - /* HELPER */ - const update = (type,value) => + const update = (type,value) => { + settings.set(type,value); + listeners + .get(type) + ?.forEach((listener) => listener(value)); + + }; + const transmit = (type,value) => port.postMessage([ type , value ]); + /* + LISTENER + */ + + let listener = (data = []) => { + + data.forEach(([ type , value ]) => + update(type,value)); + + listener = ([ type , value ]) => + update(type,value); + }; + + port.onMessage.addListener((...args) => listener(...args)); + + /* SETTING STATE */ @@ -84,6 +99,9 @@ .get(type) .add(resolve); + if(settings.has(type)) + resolve(settings.get(type)); + }; })(); diff --git a/source/source/library/Manifest.js b/source/source/library/Manifest.js index 426adc0..bb3627d 100644 --- a/source/source/library/Manifest.js +++ b/source/source/library/Manifest.js @@ -14,6 +14,8 @@ const manifest = chrome.runtime.getManifest(); + Manifest.uuid = () => + chrome.runtime.id; Manifest.version = () => manifest.version; diff --git a/source/source/library/Readify.js b/source/source/library/Readify.js new file mode 100644 index 0000000..79d6935 --- /dev/null +++ b/source/source/library/Readify.js @@ -0,0 +1,32 @@ +/* + COPYRIGHT 2021 @ LewdTechnologies + + CONTACT: + # Email: LewdTechnologies@gmail + # Website: Github.com/LewdTechnologies/Neko +*/ + + +(() => { + + window.Readify ??= {}; + + const { floor } = Math; + + + Readify.postCount = (count) => { + + if(count < 1e3) + return String(count); + + count = floor(count / 1e3); + + if(count < 1e3) + return `${ count }k`; + + count = floor(count / 1e2); + + return `${ count / 10 }M`; + }; + +})(); diff --git a/source/source/library/TagName.js b/source/source/library/TagName.js index 34d0447..890d075 100644 --- a/source/source/library/TagName.js +++ b/source/source/library/TagName.js @@ -31,8 +31,8 @@ string = string .trim() - .replace(/\w\(/,(match) => match[0] + ' (') - .replace(/ +/,' ') + .replaceAll(/\w\(/g,(match) => match[0] + ' (') + .replaceAll(/ +/g,' ') .split(/ |_/) .map(trim) .map(capitalize) diff --git a/source/source/library/overrides/Element.js b/source/source/library/overrides/Element.js new file mode 100644 index 0000000..a33b590 --- /dev/null +++ b/source/source/library/overrides/Element.js @@ -0,0 +1,35 @@ +/* + COPYRIGHT 2021 @ LewdTechnologies + + CONTACT: + # Email: LewdTechnologies@gmail + # Website: Github.com/LewdTechnologies/Neko +*/ + + +(() => { + + + /* + HELPER + */ + + const override = (name) => (func) => + Element.prototype[name] = func; + + const get = (name) => (get) => + Object.defineProperty(Element.prototype,name,{ get }); + + const set = (name) => (set) => + Object.defineProperty(Element.prototype,name,{ set }); + + + /* + ITEMS + */ + + get('items')(function(){ + return [ ...this.children ]; + }); + +})(); diff --git a/source/source/library/overrides/EventTarget.js b/source/source/library/overrides/EventTarget.js new file mode 100644 index 0000000..0a85392 --- /dev/null +++ b/source/source/library/overrides/EventTarget.js @@ -0,0 +1,32 @@ +/* + COPYRIGHT 2021 @ LewdTechnologies + + CONTACT: + # Email: LewdTechnologies@gmail + # Website: Github.com/LewdTechnologies/Neko +*/ + + +(() => { + + + /* + HELPER + */ + + const override = (name) => (func) => + EventTarget.prototype[name] = func; + + + /* + PREVENT DEFAULT ACTION + */ + + override('preventDefaultAction')(function(type){ + this.addEventListener(type,(event) => { + event.preventDefault(); + event.stopImmediatePropagation(); + }); + }); + +})(); diff --git a/source/source/library/overrides/Node.js b/source/source/library/overrides/Node.js new file mode 100644 index 0000000..8645c28 --- /dev/null +++ b/source/source/library/overrides/Node.js @@ -0,0 +1,35 @@ +/* + COPYRIGHT 2021 @ LewdTechnologies + + CONTACT: + # Email: LewdTechnologies@gmail + # Website: Github.com/LewdTechnologies/Neko +*/ + + +(() => { + + + /* + HELPER + */ + + const override = (name) => (func) => + Node.prototype[name] = func; + + const get = (name) => (get) => + Object.defineProperty(Node,name,{ get }); + + const set = (name) => (set) => + Object.defineProperty(Node,name,{ set }); + + + /* + NODES + */ + + get('nodes')(function(){ + return [ ...this.childNodes ]; + }); + +})(); diff --git a/source/source/library/overrides/String.js b/source/source/library/overrides/String.js new file mode 100644 index 0000000..45a1464 --- /dev/null +++ b/source/source/library/overrides/String.js @@ -0,0 +1,29 @@ +/* + COPYRIGHT 2021 @ LewdTechnologies + + CONTACT: + # Email: LewdTechnologies@gmail + # Website: Github.com/LewdTechnologies/Neko +*/ + + +(() => { + + + /* + HELPER + */ + + const override = (name) => (func) => + String.prototype[name] = func; + + + /* + CAPITALIZE + */ + + override('capitalize')(function(type){ + return this[0]?.toUpperCase() + this.substring(1); + }); + +})();