Untitled diff

Created Diff never expires
62 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
742 lines
44 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
735 lines
// ==UserScript==
// ==UserScript==
// @name EH Gallery Quick Favourite
// @name EH Gallery Quick Favourite
// @author FabulousCupcake
// @author FabulousCupcake
// @namespace http://fabulous.cupcake.jp.net/
// @namespace http://fabulous.cupcake.jp.net/
// @version v2.2.0
// @version v2.2.0f
// @description Upgrades the gallery favourite button to allow quick favouriting of a gallery.
// @description Upgrades the gallery favourite button to allow quick favouriting of a gallery.
// @include /^https?://(ex|(?:g\.)?e-)hentai\.org/g/\d+?/\w{10}/?/
// @include /^https?://(ex|(?:g\.)?e-)hentai\.org/g/\d+?/\w{10}/?/
// @include /^https?://(ex|(?:g\.)?e-)hentai\.org\/gallerypopups\.php\?.+&act=addfav/
// @include /^https?://(ex|(?:g\.)?e-)hentai\.org\/gallerypopups\.php\?.+&act=addfav/
// @grant none
// @grant GM.xmlHttpRequest
// ==/UserScript==
// ==/UserScript==


/* ====================================== *\
/* ====================================== *\
Hotkey Map
Hotkey Map
----
----
Shift+F : Initiate Favouriting Mode
Shift+F : Initiate Favouriting Mode
[0-9] : Favourite 0-9
[0-9] : Favourite 0-9
- : Remove Favourite
- : Remove Favourite
----
----
Pressing any other key during act-
Pressing any other key during act-
ive favouriting mode will exit the
ive favouriting mode will exit the
active favving mode.
active favving mode.
\* ====================================== */
\* ====================================== */




// Config
// Config
const config = {
const config = {
"debug": false,
"debug": false,
"editor_size": 60, // Width of the favnotes input element in not-px unit
"editor_size": 60, // Width of the favnotes input element in not-px unit
"hotkeys": true, // Enable hotkeys
"hotkeys": true, // Enable hotkeys
"cheatsheet": true // Show cheatsheet after pressing Shift+F?
"cheatsheet": true // Show cheatsheet after pressing Shift+F?
};
};


// Colors
// Colors
var geh = {
var geh = {
"border" : "#5C0D12",
"border" : "#5C0D12",
"bg" : "#E3E0D1",
"bg" : "#E3E0D1",
"bg_light" : "#F8F6EE",
"bg_light" : "#F8F6EE",
};
};
var exh = {
var exh = {
"border" : "#000000",
"border" : "#000000",
"bg" : "#4F535B",
"bg" : "#4F535B",
"bg_light" : "#5F636B",
"bg_light" : "#5F636B",
};
};
var color;
var color;
var hotkeyInit = false;
var hotkeyInit = false;


// Are we on fjords?
// Are we on fjords?
color = (location.host.substr(0,2) == "ex" ) ?
color = (location.host.substr(0,2) == "ex" ) ?
color = exh :
color = exh :
color = geh;
color = geh;


// Stylesheet
// Stylesheet
var stylesheet =`
var stylesheet =`
#gdf {
#gdf {
margin: 6px 0 !important;
margin: 6px 0 !important;
padding: 10px 5px !important;
padding: 10px 5px !important;
width: 160px !important;
width: 160px !important;
height: 18px;
height: 18px;
position: relative;
position: relative;
border: 1px dashed ${color.border};
border: 1px dashed ${color.border};
left: -2px !important;
left: -2px !important;
}
}


#gdf > div:nth-child(1),
#gdf > div:nth-child(1),
#gdf > div:nth-child(2),
#gdf > div:nth-child(2),
#gdf > div:nth-child(3) {
#gdf > div:nth-child(3) {
display: inline !important;
display: inline !important;
float: none !important;
float: none !important;
}
}


#gdf > div:nth-child(2) > a {
#gdf > div:nth-child(2) > a {
position: relative;
position: relative;
top: -1px;
top: -1px;
line-height: 21px;
line-height: 21px;
}
}


#gdf > #fav {
#gdf > #fav {
padding-left: 5px;
padding-left: 5px;
}
}


#gdf > #fav > * {
#gdf > #fav > * {
float: none !important;
float: none !important;
display: inline-block !important;
display: inline-block !important;
margin: 0 !important;
margin: 0 !important;
position: relative;
position: relative;
top: 2px;
top: 2px;
}
}


#gdf div.i {
#gdf div.i {
display: inline-block;
display: inline-block;
margin: 0 !important;
margin: 0 !important;
}
}


#gdf a:hover {
#gdf a:hover {
color: inherit !important;
color: inherit !important;
}
}


.qf-top, .qf-bot {
.qf-top, .qf-bot {
background: ${color.bg_light} !important;
background: ${color.bg_light} !important;
width: inherit;
width: inherit;
padding: 0 5px;
padding: 0 5px;
position: absolute;
position: absolute;
left: -1px;
left: -1px;
visibility: hidden;
visibility: hidden;
border: 1px solid ${color.border};
border: 1px solid ${color.border};
}
}


.qf-top {
.qf-top {
border-bottom: none;
border-bottom: none;
padding-top: 5px;
padding-top: 5px;
bottom: 33px;
bottom: 33px;
}
}


.qf-bot {
.qf-bot {
border-top: none;
border-top: none;
padding-bottom: 5px;
padding-bottom: 5px;
top: 33px;
top: 33px;
}
}


#gdf .fav {
#gdf .fav {
box-sizing: border-box;
box-sizing: border-box;
cursor: pointer;
cursor: pointer;
padding: 5px;
padding: 5px;
text-align: left;
text-align: left;
width: 100%;
width: 100%;
}
}


#gdf .fav:hover {
#gdf .fav:hover {
background: ${color.bg};
background: ${color.bg};
}
}


#gdf:hover,
#gdf:hover,
#gdf.hover {
#gdf.hover {
border: 1px solid ${color.border};
border: 1px solid ${color.border};
}
}


#gdf:hover > .qf-top,
#gdf:hover > .qf-top,
#gdf:hover > .qf-bot,
#gdf:hover > .qf-bot,
#gdf.hover > .qf-top,
#gdf.hover > .qf-top,
#gdf.hover > .qf-bot {
#gdf.hover > .qf-bot {
visibility: visible;
visibility: visible;
}
}


#gdf > .favnote {
#gdf > .favnote {
float: right !important;
float: right !important;
cursor: pointer;
cursor: pointer;
width: 16px;
width: 16px;
height: 16px;
height: 16px;
margin-right: 5px;
margin-right: 5px;
position: relative;
position: relative;
top: 1px;
top: 1px;
z-index: 20;
z-index: 20;
opacity: 0.5;
opacity: 0.5;
}
}


#gdf > .favnote:hover {
#gdf > .favnote:hover {
opacity: 1;
opacity: 1;
}
}


#gdf > .favnote:after {
#gdf > .favnote:after {
opacity: 0;
opacity: 0;
}
}


#gdf > .favnote:hover:after {
#gdf > .favnote:hover:after {
display: block;
display: block;
padding: 0 5px;
padding: 0 5px;
height: 20px;
height: 20px;
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
background: #f4f4f4;
background: #f4f4f4;
color: #333;
color: #333;
font-weight: 400;
font-weight: 400;
font-size: 11px;
font-size: 11px;
line-height: 20px;
line-height: 20px;
position: absolute;
position: absolute;
top: -20px;
top: -20px;
left: 0px;
left: 0px;
transition: opacity 300ms cubic-bezier(1, -1, 1, -1);
transition: opacity 300ms cubic-bezier(1, -1, 1, -1);
opacity: 1
opacity: 1
}
}


/* ========================================= *\
/* ========================================= *\
* Fugue Icons v3.5.6 by Yusuke Kamiyamane *
* Fugue Icons v3.5.6 by Yusuke Kamiyamane *
* http://p.yusukekamiyamane.com/ *
* http://p.yusukekamiyamane.com/ *
\* ========================================= */
\* ========================================= */
#gdf > .favnote { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABQ0lEQVR4AcWONZoVURBGTxXusgrcIcMhw3dCjC/hxewB9wR3SXAYJGKS5zLW91bBK9wd/u6+2ud8P/89AnDjsOwBZvBjKS1a7xd4k+EAZsyav2zvFkst3A08Y1aQUz85D2C5AKC39ymdyhG9dlBkyUY/D6BvBIINYkUtvlw0sNTG8iCpSAwNFQwMDMS3eO2pLWZsvbJfln3YQEARkTdOi3nYsOG8TUpDNJtNzpzYDizZXHlxbQqwMv7IGRVRVBUz+6pk+vSFmGVGjx7N3XStCfCRQES+J4kmb5l3gpRRQhDQdyX6ah3Mxw0Euh/fkYRg1OcNBMWRcHxPosPHfNIgoUgXFtz5rkR1RDDvBH39PhKdiIwAcccxcCPWMVvA7hk3Q3RkMG8FU2/d4Vm7tHk0P5FHz3nWZQUYA0wI2c8lAS1+Ny8BF2m6Eor51N8AAAAASUVORK5CYII='); }
#gdf > .favnote { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABQ0lEQVR4AcWONZoVURBGTxXusgrcIcMhw3dCjC/hxewB9wR3SXAYJGKS5zLW91bBK9wd/u6+2ud8P/89AnDjsOwBZvBjKS1a7xd4k+EAZsyav2zvFkst3A08Y1aQUz85D2C5AKC39ymdyhG9dlBkyUY/D6BvBIINYkUtvlw0sNTG8iCpSAwNFQwMDMS3eO2pLWZsvbJfln3YQEARkTdOi3nYsOG8TUpDNJtNzpzYDizZXHlxbQqwMv7IGRVRVBUz+6pk+vSFmGVGjx7N3XStCfCRQES+J4kmb5l3gpRRQhDQdyX6ah3Mxw0Euh/fkYRg1OcNBMWRcHxPosPHfNIgoUgXFtz5rkR1RDDvBH39PhKdiIwAcccxcCPWMVvA7hk3Q3RkMG8FU2/d4Vm7tHk0P5FHz3nWZQUYA0wI2c8lAS1+Ny8BF2m6Eor51N8AAAAASUVORK5CYII='); }
#gdf > .favnote.plus { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABl0lEQVR4AcWOA4xeQRRGz0xtM6gd1DbCmjFquw3qWGVUx6lt27Ztt+vdN3OnndWPddTv4frk479LAVzfp5YATcmfVrbu585HAK7uUTtadF03WEwszgk4i0iANYlYm4TYAIBPn14S/2P/TmBF2wHuHIAGEEEhyUjwy3/Y4A9i4hCbjAkMKSkBSUlJ+K9Nn6ODRZhxeZfqClA4E4BGKYWPIPhYqFBhMmRMCjExMZw+PB9oO+jHx6sVgB6FAaxFK6XRWiMiOUKaNGmFiKV48eI8MFdjACIASqk8Id5Jxk0mwPgiFaAByROi/+X+BkCT6UDhvzAnEbWPM15fpveTw8x6cx0bDvA0hQZyh9z6/Y3WHftx8/fXKAcGTbqD7CBT7p+m06VtYBx/7B+UgbGubHvWV1yjADav5MyIUbu6IjHgHA7BOfG5j7Q7soqy3RsRrVM7T95QQMW5Y1jWsDZNyEEbi5So81oVKglQcUSLUj+33IpPcSR9f+n2A5QAqgI18/wWl7pT81Uz52P6TQkKpClF1zChyHUfSddf7UXJLEn3VbsAAAAASUVORK5CYII='); }
#gdf > .favnote.plus { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABl0lEQVR4AcWOA4xeQRRGz0xtM6gd1DbCmjFquw3qWGVUx6lt27Ztt+vdN3OnndWPddTv4frk479LAVzfp5YATcmfVrbu585HAK7uUTtadF03WEwszgk4i0iANYlYm4TYAIBPn14S/2P/TmBF2wHuHIAGEEEhyUjwy3/Y4A9i4hCbjAkMKSkBSUlJ+K9Nn6ODRZhxeZfqClA4E4BGKYWPIPhYqFBhMmRMCjExMZw+PB9oO+jHx6sVgB6FAaxFK6XRWiMiOUKaNGmFiKV48eI8MFdjACIASqk8Id5Jxk0mwPgiFaAByROi/+X+BkCT6UDhvzAnEbWPM15fpveTw8x6cx0bDvA0hQZyh9z6/Y3WHftx8/fXKAcGTbqD7CBT7p+m06VtYBx/7B+UgbGubHvWV1yjADav5MyIUbu6IjHgHA7BOfG5j7Q7soqy3RsRrVM7T95QQMW5Y1jWsDZNyEEbi5So81oVKglQcUSLUj+33IpPcSR9f+n2A5QAqgI18/wWl7pT81Uz52P6TQkKpClF1zChyHUfSddf7UXJLEn3VbsAAAAASUVORK5CYII='); }
#gdf > .favnote.arrow { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABnUlEQVR4Ac2QA6weURCFt7bduHZc27YV1bZt+9m2bdu2bRvn7Tz8ZthJvsXdPd+ducz/UeF2/V6zmMnIaiFBqE0/i7YqdbSU/URz6Xc0l3xBY9F71OU9Q3X2PVRm3ASR4L8H9C/LGj5BsFU/y7YKBTQVvkBjwTM05D9Ffd5j1GTfR3naLRQnXUFhwkVEuG8BGt1A/7Os5QgCLfpZtVUoobnopUSJl+UyDub/+nlxBH6m/WzaK1XQWvKaJFI7oXEowxF4G/Wz66hSQ1vpG5kkJKAMR+Cu38+ho1oD7WXvZJLQwVKGI3DR6efUWaOJjvL3UiUfnF1hF2YAynAEDpr9XFCjzQo+SJWc0Q/DWYMIvFE9HccR2Kr2c0OtDjorPgpJXlrY4JiqD4GjhIo3lAqAjV9saxa/jz7NUBn/ZnxQbwWSUCfd41Srgw527y83/MkDriQAZ2K43E0GZj72C6f8+AfnGW3190yIKHbcu1O65IZSPS/LA4B51zTKx+14dpEEw1gms0yXhVEn9WKIkQf+nO/NyleDD6irsJzue+8CGCvzmWahQigAAAAASUVORK5CYII='); }
#gdf > .favnote.arrow { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABnUlEQVR4Ac2QA6weURCFt7bduHZc27YV1bZt+9m2bdu2bRvn7Tz8ZthJvsXdPd+ducz/UeF2/V6zmMnIaiFBqE0/i7YqdbSU/URz6Xc0l3xBY9F71OU9Q3X2PVRm3ASR4L8H9C/LGj5BsFU/y7YKBTQVvkBjwTM05D9Ffd5j1GTfR3naLRQnXUFhwkVEuG8BGt1A/7Os5QgCLfpZtVUoobnopUSJl+UyDub/+nlxBH6m/WzaK1XQWvKaJFI7oXEowxF4G/Wz66hSQ1vpG5kkJKAMR+Cu38+ho1oD7WXvZJLQwVKGI3DR6efUWaOJjvL3UiUfnF1hF2YAynAEDpr9XFCjzQo+SJWc0Q/DWYMIvFE9HccR2Kr2c0OtDjorPgpJXlrY4JiqD4GjhIo3lAqAjV9saxa/jz7NUBn/ZnxQbwWSUCfd41Srgw527y83/MkDriQAZ2K43E0GZj72C6f8+AfnGW3190yIKHbcu1O65IZSPS/LA4B51zTKx+14dpEEw1gms0yXhVEn9WKIkQf+nO/NyleDD6irsJzue+8CGCvzmWahQigAAAAASUVORK5CYII='); }
#gdf > .favnote.pencil { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABwElEQVR4Ac2QA4yYMQCF23nRfEMwe4sz27Zt297Ztm3btm3btt/+XnJmvJfU/b6C/B+JdKB8XLGYYNlFhibcjlp11GiirUIGreVSaC0TR3OJEBoKfqE29xOqs96ClaTA02B7ubJ7kCDUhlp3VCmhpfgPmot+oanwJxoLvqMu9zMqM96hNOUFipOeIsrzMNDsAbafK3v6BMFW1KajSgWtJX/HlPhYb+0rlorUp08QYE7tOqvV0F7GxyTj3oQ9hzF9Al8T6tBVo4GOcv4JSUqtriJlAy0NpnQfYfE0pE5dtVrorBAcV5IS+gqu4hcBXl7YUepHWNz0qEt3nTa6KoXGlBTF34KF3kO0tLTg64nZOTqEHCEsTtrUDXW6nEB4VElJ4h0EWq/m+t8hLXwZCrzTgvv+wF6deqBeD91VIiNKypLvI8hmDYNhpboM6eEvwZg+gakc8UOjDZiE3aTnObWaYB9bkf4OwbabGQwb9TXIinyD9kplMKaXn/vlMdHVFCJhQ4u2IImzUKC1DFb+S+tVeElq7xpjGMsVMpMrPFxZMrQIPKRSaEyD7Hca9PAiuTBknaeHHSd4dpZafL1Ld4+24R9mFfDtXW/67AAAAABJRU5ErkJggg=='); }
#gdf > .favnote.pencil { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABwElEQVR4Ac2QA4yYMQCF23nRfEMwe4sz27Zt297Ztm3btm3btt/+XnJmvJfU/b6C/B+JdKB8XLGYYNlFhibcjlp11GiirUIGreVSaC0TR3OJEBoKfqE29xOqs96ClaTA02B7ubJ7kCDUhlp3VCmhpfgPmot+oanwJxoLvqMu9zMqM96hNOUFipOeIsrzMNDsAbafK3v6BMFW1KajSgWtJX/HlPhYb+0rlorUp08QYE7tOqvV0F7GxyTj3oQ9hzF9Al8T6tBVo4GOcv4JSUqtriJlAy0NpnQfYfE0pE5dtVrorBAcV5IS+gqu4hcBXl7YUepHWNz0qEt3nTa6KoXGlBTF34KF3kO0tLTg64nZOTqEHCEsTtrUDXW6nEB4VElJ4h0EWq/m+t8hLXwZCrzTgvv+wF6deqBeD91VIiNKypLvI8hmDYNhpboM6eEvwZg+gakc8UOjDZiE3aTnObWaYB9bkf4OwbabGQwb9TXIinyD9kplMKaXn/vlMdHVFCJhQ4u2IImzUKC1DFb+S+tVeElq7xpjGMsVMpMrPFxZMrQIPKRSaEyD7Hca9PAiuTBknaeHHSd4dpZafL1Ld4+24R9mFfDtXW/67AAAAABJRU5ErkJggg=='); }
#gdf > .favnote.exclamation { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB5ElEQVR4AcWQA4yfMQBHXzvbtm3b4RzNXow5mIPZWzTbtm3btre/1a/dXXN2uF9St6+v5b9HANw8IKYDNclYFjfuZi4mAlzfJ3Y1aLuit1YejNFgHLSO4KgAjhNEOxEAvnx5je/Xwd3AoqY9zAUACaA1Ah1CR/7Y4kRcaOVFOyFURBEORwgGg7Y06XK8t9aMvrpHtAXIHAdAIoSIYWrbZspkl22UCuN2uzl7dBLQtNevz9cLAB3sDsdBCiGRUqK1ThVSo0YjtHbInj07j9R1N9idcQBrIKVto0pcayEB33P+fD9J0PuC2DNxT1DRA3vA3pzUxPaDvs+UrT2eD48W233RZ5IYCGxJwcTneUuOfLXIlj0/uQrUIhT4FmcgYw2E7aYEAdfvF+QtXJ++Q7aTt2AtXH9eRgMyEWegkMQYJIV4XO/IlLUIRrnYsWMHfs9nNNkRgkJxf+APmKzIvIgsIIzBoMFoRFT5EfVxeYpW4fOf6xw6OJ4fwRtkypEVbSgxsJe9koITRrKganlqkCTZsoncJUsXKFupQf3cjnJRqdYtXj1qBAhe3Xv6bdUm32AB5ADyWJskWTlTLGzVrmKngkWyFsIYchfqhffXHgB+//T+vH/r0yFBGlk/l2Va05BUIiW3/wHmcuCUyEztWwAAAABJRU5ErkJggg=='); }
#gdf > .favnote.exclamation { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB5ElEQVR4AcWQA4yfMQBHXzvbtm3b4RzNXow5mIPZWzTbtm3btre/1a/dXXN2uF9St6+v5b9HANw8IKYDNclYFjfuZi4mAlzfJ3Y1aLuit1YejNFgHLSO4KgAjhNEOxEAvnx5je/Xwd3AoqY9zAUACaA1Ah1CR/7Y4kRcaOVFOyFURBEORwgGg7Y06XK8t9aMvrpHtAXIHAdAIoSIYWrbZspkl22UCuN2uzl7dBLQtNevz9cLAB3sDsdBCiGRUqK1ThVSo0YjtHbInj07j9R1N9idcQBrIKVto0pcayEB33P+fD9J0PuC2DNxT1DRA3vA3pzUxPaDvs+UrT2eD48W233RZ5IYCGxJwcTneUuOfLXIlj0/uQrUIhT4FmcgYw2E7aYEAdfvF+QtXJ++Q7aTt2AtXH9eRgMyEWegkMQYJIV4XO/IlLUIRrnYsWMHfs9nNNkRgkJxf+APmKzIvIgsIIzBoMFoRFT5EfVxeYpW4fOf6xw6OJ4fwRtkypEVbSgxsJe9koITRrKganlqkCTZsoncJUsXKFupQf3cjnJRqdYtXj1qBAhe3Xv6bdUm32AB5ADyWJskWTlTLGzVrmKngkWyFsIYchfqhffXHgB+//T+vH/r0yFBGlk/l2Va05BUIiW3/wHmcuCUyEztWwAAAABJRU5ErkJggg=='); }


#gdf > .favnote:after { width: 70px; content: "See your note"; }
#gdf > .favnote:after { width: 70px; content: "See your note"; }
#gdf > .favnote.plus:after { width: 55px; content: "Add a note"; }
#gdf > .favnote.plus:after { width: 55px; content: "Add a note"; }
#gdf > .favnote.arrow:after { width: 70px; content: "Save the note"; }
#gdf > .favnote.arrow:after { width: 70px; content: "Save the note"; }
#gdf > .favnote.pencil:after { width: 70px; content: "Edit your note"; }
#gdf > .favnote.pencil:after { width: 70px; content: "Edit your note"; }
#gdf > .favnote.exclamation:after { width: 300px; height: 60px !important; white-space: normal; content: "Note failed to load. Click to retry. WARNING: Changing favourite category while the note is not loaded will remove existing notes!"; }
#gdf > .favnote.exclamation:after { width: 300px; height: 60px !important; white-space: normal; content: "Note failed to load. Click to retry. WARNING: Changing favourite category while the note is not loaded will remove existing notes!"; }


#gdf > .favnote + .editor {
#gdf > .favnote + .editor {
position: absolute;
position: absolute;
height: 18px;
height: 18px;
background: ${color.bg_light} !important;
background: ${color.bg_light} !important;
padding: 10px;
padding: 10px;
top: -1px;
top: -1px;
left: 132px;
left: 132px;
z-index: 10;
z-index: 10;
border: 1px solid ${color.border};
border: 1px solid ${color.border};
visibility: hidden;
visibility: hidden;
}
}


#gdf > .favnote + .editor > input {
#gdf > .favnote + .editor > input {
margin: 0 0 0 30px;
margin: 0 0 0 30px;
height: 12px;
height: 12px;
}
}


#gdf > .favnote + .editor > input.notinput {
#gdf > .favnote + .editor > input.notinput {
border-color: transparent;
border-color: transparent;
background: none !important;
background: none !important;
color: inherit !important;
color: inherit !important;
cursor: default !important;
cursor: default !important;
outline: none !important;
outline: none !important;
color: transparent !important;
color: transparent !important;
text-shadow: 0 0 0 ${color.border};
text-shadow: 0 0 0 ${color.border};
}
}


#gdf > .favnote + .editor.show { visibility: visible; }
#gdf > .favnote + .editor.show { visibility: visible; }


#gdf.hover .fav {
#gdf.hover .fav {
position: relative;
position: relative;
}
}


#gdf .hotkey-hint {
#gdf .hotkey-hint {
position: absolute;
position: absolute;
top: 4px;
top: 4px;
right: 0;
right: 0;
box-sizing: border-box;
box-sizing: border-box;
padding: 0 1px 0 2px;
padding: 0 1px 0 2px;
border: 1px solid #888;
border: 1px solid #888;
border-radius: 2px;
border-radius: 2px;
background: #eee;
background: #eee;
color: #666 !important;
color: #666 !important;
font-family: monospace;
font-family: monospace;
font-size: 13px;
font-size: 13px;
box-shadow: -3px 0 2px 2px ${color.bg_light};
box-shadow: -3px 0 2px 2px ${color.bg_light};
visibility: hidden;
visibility: hidden;
}
}


#gdf.hover .fav:hover .hotkey-hint {
#gdf.hover .fav:hover .hotkey-hint {
box-shadow: -3px 0 2px 2px ${color.bg};
box-shadow: -3px 0 2px 2px ${color.bg};
}
}


#gdf.hover .hotkey-hint {
#gdf.hover .hotkey-hint {
visibility: visible;
visibility: visible;
}
}


`;
`;


/* ========================================================================= *\
/* ========================================================================= *\
* * UTILITY FUNCTIONS
* * UTILITY FUNCTIONS
\* ========================================================================= */
\* ========================================================================= */
// Debug msg
// Debug msg
function dlog(msg) {
function dlog(...msg) {
if ( config.debug ) {
if ( config.debug ) {
console.log(`"EHGQF: ${msg}`);
console.log("EHGQF:", ...msg);
}
}
}
}


// Get the actual/current favourite category of the current gallery
// Get the actual/current favourite category of the current gallery
function getPageFavId() {
function getPageFavId() {
let idElement = document.querySelector("#fav .i");
let idElement = document.querySelector("#fav .i");
if ( !idElement ) return 10;
if ( !idElement ) return 10;


return (idElement.style.backgroundPositionY.match(/\d+/)[0] - 2)/19;
return (idElement.style.backgroundPositionY.match(/\d+/)[0] - 2)/19;
}
}




/* ========================================================================= *\
/* ========================================================================= *\
* * UI INJECTIONS
* * UI INJECTIONS
\* ========================================================================= */
\* ========================================================================= */
// Inject CSS
// Inject CSS
function injectStylesheet() {
function injectStylesheet() {
dlog("Injecting stylesheet");
dlog("Injecting stylesheet");
var stylesheetEl = document.createElement("style");
var stylesheetEl = document.createElement("style");
stylesheetEl.innerHTML = stylesheet;
stylesheetEl.innerHTML = stylesheet;
document.body.appendChild(stylesheetEl);
document.body.appendChild(stylesheetEl);
}
}


// Build and inject FavNote UI
// Build and inject FavNote UI
function injectFavnoteElements() {
function injectFavnoteElements() {
dlog("Injecting Favnote UI elements");
dlog("Injecting Favnote UI elements");


// Fetch the FavID of the current gallery
// Fetch the FavID of the current gallery
var curFavID = getPageFavId();
var curFavID = getPageFavId();


// Fetch favnotes if current gallery was already in a fav category
// Fetch favnotes if current gallery was already in a fav category
if ( curFavID != 10 ) {
if ( curFavID != 10 ) {
fetchFavouriteNotes( favnote => {
fetchFavouriteNotes( favnote => {


// Determine icon type
// Determine icon type
var favnoteStatus = "";
var favnoteStatus = "";
if ( favnote === false ) favnoteStatus = "exclamation";
if ( favnote === false ) favnoteStatus = "exclamation";
if ( favnote === "" ) favnoteStatus = "plus";
if ( favnote === "" ) favnoteStatus = "plus";


// Build elements for Favnotes
// Build elements for Favnotes
var favnoteEl = `
var favnoteEl = `
<div class='favnote ${favnoteStatus}'></div>
<div class='favnote ${favnoteStatus}'></div>
<div class="editor">
<div class="editor">
<input type="text" size="${config.editor_size}" class="stdinput" value="${favnote}">
<input type="text" size="${config.editor_size}" class="stdinput" value="${favnote}">
</div>
</div>
`;
`;


// Inject
// Inject
var gdf = document.getElementById("gdf");
var gdf = document.getElementById("gdf");
gdf.insertAdjacentHTML("beforeend", favnoteEl);
gdf.insertAdjacentHTML("beforeend", favnoteEl);


// Add event listeners
// Add event listeners
document.querySelector("#gdf > .favnote").addEventListener("click", favnoteClick);
document.querySelector("#gdf > .favnote").addEventListener("click", favnoteClick);


dlog("Successfully injected Favnote UI");
dlog("Successfully injected Favnote UI");
return;
return;
});
});
}
}
dlog("FavID = 10: No notes to inject!");
dlog("FavID = 10: No notes to inject!");
}
}


// Build & Inject QF UI
// Build & Inject QF UI
function injectQFElements() {
function injectQFElements() {
var i;
var i;
dlog("Injecting Quick Fav UI elements");
dlog("Injecting Quick Fav UI elements");


// Fetch the FavID of the current gallery
// Fetch the FavID of the current gallery
var curFavID = getPageFavId();
var curFavID = getPageFavId();


// Fetch the Labels of the 10 Fav items
// Fetch the Labels of the 10 Fav items
var favLabels = [];
var favLabels = [];
for (i=0; i<10; i++) {
for (i=0; i<10; i++) {
var label = localStorage.getItem(`EHGQF-fav${i}`);
var label = localStorage.getItem(`EHGQF-fav${i}`);
if ( !label ) label = `Favorites ${i+1}`;
if ( !label ) label = `Favorites ${i+1}`;
favLabels.push(label);
favLabels.push(label);
}
}


// Build fav item elements
// Build fav item elements
var favEl = [];
var favEl = [];
for (i=0; i<10; i++) {
for (i=0; i<10; i++) {
var offset = 2 + (i*19);
var offset = 2 + (i*19);
var el = `
var el = `
<div qfid='${i}' class='fav'>
<div qfid='${i}' class='fav'>
<div class="i" style="background-image:url(https://ehgt.org/g/fav.png); background-position:0px -${offset}px;"></div>
<div class="i" style="background-image:url(https://ehgt.org/g/fav.png); background-position:0px -${offset}px;"></div>
&nbsp; <a id="favoritelink" href="#">${favLabels[i]}</a>
&nbsp; <a id="favoritelink" href="#">${favLabels[i]}</a>
<div class="hotkey-hint">${i}</div>
<div class="hotkey-hint">${i}</div>
</div>
</div>
`;
`;
favEl.push(el);
favEl.push(el);
}
}


// Add the `remove favorites` fav item
// Add the `remove favorites` fav item
favEl.push(`
favEl.push(`
<div qfid='favdel' class='fav'>
<div qfid='favdel' class='fav'>
<a id="favoritelink" href="#">Remove from Favorites</a>
<a id="favoritelink" href="#">Remove from Favorites</a>
<div class="hotkey-hint">-</div>
<div class="hotkey-hint">-</div>
</div>
</div>
`);
`);


// Build top list
// Build top list
var qfTopElContent = "";
var qfTopElContent = "";
for (i=0; i<curFavID; i++) { qfTopElContent += favEl[i]; }
for (i=0; i<curFavID; i++) { qfTopElContent += favEl[i]; }
var qfTopEl = `<div class='qf-top'>${qfTopElContent}</div>`;
var qfTopEl = `<div class='qf-top'>${qfTopElContent}</div>`;


// Build bottom list
// Build bottom list
var qfBotElContent = "";
var qfBotElContent = "";
for (i=curFavID+1; i<favEl.length; i++) { qfBotElContent += favEl[i]; }
for (i=curFavID+1; i<favEl.length; i++) { qfBotElContent += favEl[i]; }
var qfBotEl = `<div class='qf-bot'>${qfBotElContent}</div>`;
var qfBotEl = `<div class='qf-bot'>${qfBotElContent}</div>`;


// Inject Elements! Finally
// Inject Elements! Finally
var gdf = document.getElementById("gdf");
var gdf = document.getElementById("gdf");
gdf.insertAdjacentHTML("beforeend", qfTopEl);
gdf.insertAdjacentHTML("beforeend", qfTopEl);
gdf.insertAdjacentHTML("beforeend", qfBotEl);
gdf.insertAdjacentHTML("beforeend", qfBotEl);


// Add Event Listeners
// Add Event Listeners
var favDOMEl = document.querySelectorAll("#gdf .fav");
var favDOMEl = document.querySelectorAll("#gdf .fav");
for(i=0; i<favDOMEl.length; i++) {
for(i=0; i<favDOMEl.length; i++) {
favDOMEl[i].addEventListener("click", quickFavourite);
favDOMEl[i].addEventListener("click", quickFavourite);
}
}


// Disable `#gdf` click event; move it to its child element;
// Disable `#gdf` click event; move it to its child element;
gdf.children[0].onclick = gdf.onclick;
gdf.children[0].onclick = gdf.onclick;
gdf.children[1].onclick = gdf.onclick;
gdf.children[1].onclick = gdf.onclick;
gdf.onclick = "";
gdf.onclick = "";


dlog("UI Injection successful!");
dlog("UI Injection successful!");
}
}




/* ========================================================================= *\
/* ========================================================================= *\
* * QUICK FAVOURITE
* * QUICK FAVOURITE
\* ========================================================================= */
\* ========================================================================= */
// Send Favouriting XHR request to EH server
// Send Favouriting XHR request to EH server
function quickFavourite(id) {
function quickFavourite(id) {
dlog("quickFavourite() triggered!");
dlog("quickFavourite() triggered!");


// Gather and build things
// Gather and build things
let favnoteEl = document.querySelector(".favnote + .editor > input");
let favnoteEl = document.querySelector(".favnote + .editor > input");
let favnote = (favnoteEl) ? favnoteEl.value : "";
let favnote = (favnoteEl) ? favnoteEl.value : "";
let favID;
let favID;
try { favID = this.attributes.qfid.value; } catch(e) {
try { favID = this.attributes.qfid.value; } catch(e) {
favID = id;
favID = id;
}
}
let galID = location.pathname.match(/^\/\w\/(\d+)\//)[1];
let galID = location.pathname.match(/^\/\w\/(\d+)\//)[1];
let token = location.pathname.match(/\/(\w+)\/$/)[1];
let token = location.pathname.match(/\/(\w+)\/$/)[1];
let prot = location.protocol;
let prot = location.protocol;
let host = location.host;
let host = location.host;
let url = `${prot}//${host}/gallerypopups.php?gid=${galID}&t=${token}&act=addfav`;
let url = `${prot}//${host}/gallerypopups.php?gid=${galID}&t=${token}&act=addfav`;
let dat = `apply=Add to Favorites&favcat=${favID}&favnote=${favnote}&update=1`;
let dat = `apply=Add to Favorites&favcat=${favID}&favnote=${favnote}&update=1`;


// Prepare to send XHR
let xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

// Remove Quick Favourite Elements to prevent sending multiple XHR
// Remove Quick Favourite Elements to prevent sending multiple XHR
document.querySelector(".qf-top").remove();
document.querySelector(".qf-top").remove();
document.querySelector(".qf-bot").remove();
document.querySelector(".qf-bot").remove();
if ( favnoteEl ) document.querySelector(".favnote").remove();
if ( favnoteEl ) document.querySelector(".favnote").remove();
if ( favnoteEl ) document.querySelector(".editor").remove();
if ( favnoteEl ) document.querySelector(".editor").remove();


// Send XHR
// Send XHR
xhr.send(dat);
GM.xmlHttpRequest({

method: "POST",
// Update UI if request was successful
url: url,
xhr.onload = function() {
data: dat,
if (xhr.status == 200) {
headers: {
updateCurrentFav(favID); // Update #gdf
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
onload: function(response) {
if (response.status == 200) {
updateCurrentFav(favID); // Update #gdf
} else {
} else {
dlog("Error occurred! Favorite was not updated!");
dlog("Error occurred! Favorite was not updated!");
alert("Error occurred! Favorite was not updated!");
alert("Error occurred! Favorite was not updated!");
}
}


injectQFElements(); // Reinject Quick Favourite UI
injectQFElements(); // Reinject Quick Favourite UI
injectFavnoteElements(); // and Favnote UI
injectFavnoteElements(); // and Favnote UI
disableHotkeys();
disableHotkeys();
dlog("quickFavourite() done!"); // Done!
dlog("quickFavourite() done!"); // Done!
};
},
});
}
}


// Update the current/actual Favourite Category of the current Gallery
// Update the current/actual Favourite Category of the current Gallery
function updateCurrentFav(favID) {
function updateCurrentFav(favID) {
dlog("Updating current fav with favID "+favID);
dlog("Updating current fav with favID "+favID);


// If id is not specified, refresh
// If id is not specified, refresh
if ( typeof favID == "undefined" ) {
if ( typeof favID == "undefined" ) {
favID = getPageFavId();
favID = getPageFavId();
dlog("FavID set to " + favID);
dlog("FavID set to " + favID);
}
}


var el;
var el;


if (favID == "favdel" || favID === 10) {
if (favID == "favdel" || favID === 10) {
el = `
el = `
<div style="float:left">
<div style="float:left">
&nbsp; <a onclick="return false" href="#" id="favoritelink"><img src="https://ehgt.org/g/mr.gif"> Add to Favorites</a>
&nbsp; <a onclick="return false" href="#" id="favoritelink"><img src="https://ehgt.org/g/mr.gif"> Add to Favorites</a>
<div class="hotkey-hint"></div>
<div class="hotkey-hint"></div>
</div>
</div>
`;
`;
} else {
} else {
// Fetch the Labels of the 10 Fav items
// Fetch the Labels of the 10 Fav items
var favLabels = [];
var favLabels = [];
for (let i=0; i<10; i++) {
for (let i=0; i<10; i++) {
var label = localStorage.getItem(`EHGQF-fav${i}`);
var label = localStorage.getItem(`EHGQF-fav${i}`);
if ( !label ) label = `Favorites ${i}`;
if ( !label ) label = `Favorites ${i}`;
favLabels.push(label);
favLabels.push(label);
}
}


// Calculate bg offset
// Calculate bg offset
var offset = 2 + (favID*19);
var offset = 2 + (favID*19);


// Build
// Build
el = `
el = `
<div id="fav" style="float:left; cursor:pointer">
<div id="fav" style="float:left; cursor:pointer">
<div title="Read Later" style="background-image:url(https://ehgt.org/g/fav.png); background-position:0px -${offset}px;" class="i"></div>
<div title="Read Later" style="background-image:url(https://ehgt.org/g/fav.png); background-position:0px -${offset}px;" class="i"></div>
</div>
</div>
<div style="float:left">&nbsp;
<div style="float:left">&nbsp;
<a onclick="return false" href="#" id="favoritelink">${favLabels[favID]}</a>
<a onclick="return false" href="#" id="favoritelink">${favLabels[favID]}</a>
</div>
</div>
`;
`;
}
}


document.getElementById("gdf").innerHTML = el;
document.getElementById("gdf").innerHTML = el;
}
}


/* ========================================================================= *\
/* ========================================================================= *\
* * FAVOURITE NOTES
* * FAVOURITE NOTES
\* ========================================================================= */
\* ========================================================================= */
// Get Favourite Notes remotely from the popup
// Get Favourite Notes remotely from the popup
function fetchFavouriteNotes(cb) {
function fetchFavouriteNotes(cb) {
dlog("Beginning to check favnotes");
dlog("Beginning to check favnotes");


// Send XHR to Favourite Page
// Send XHR to Favourite Page
var galID = location.pathname.match(/^\/\w\/(\d+)\//)[1];
var galID = location.pathname.match(/^\/\w\/(\d+)\//)[1];
var token = location.pathname.match(/\/(\w+)\/$/)[1];
var token = location.pathname.match(/\/(\w+)\/$/)[1];
var prot = location.protocol;
var prot = location.protocol;
var host = location.host;
var host = location.host;
var url = `${prot}//${host}/gallerypopups.php?gid=${galID}&t=${token}&act=addfav`;
var url = `${prot}//${host}/gallerypopups.php?gid=${galID}&t=${token}&act=addfav`;


var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
GM.xmlHttpRequest({
xhr.timeout = config.timeout;
method: "GET",
xhr.responseType = "document";
url: url,
xhr.send();
timeout: config.timeout,

onload: function(response) {
// And grab the favnotes
if (response.status === 200) {
xhr.onload = function() {
const responseXML = new DOMParser().parseFromString(response.responseText, "text/xml");
if ( xhr.status == 200 ) {
var favnoteEl = responseXML.querySelector("textarea[name='favnote']");
// grab it!
dlog("Favnotes successfully found");
var data = xhr.response;
cb(favnoteEl.value); // Fire callback function
var favnoteEl = data.querySelector("textarea[name='favnote']");
dlog("Favnotes successfully found");
cb(favnoteEl.value); // Fire callback function
} else {
} else {
dlog("XHR failed; notes not found");
dlog("XHR failed; notes not found");
return false;
}
}
};
},

ontimeout: function() {
xhr.timeout = function() {
dlog("XHR timed out; notes not found");
dlog("XHR timed out; notes not found");
return false;
return false;
};
},

});
}
}


// Update favnote icon status
// Update favnote icon status
function updateFavnoteIcon(status) {
function updateFavnoteIcon(status) {
dlog(`Updating favnote icon to ${status}`);
dlog(`Updating favnote icon to ${status}`);
var favnoteEl = document.querySelector("#gdf > .favnote");
var favnoteEl = document.querySelector("#gdf > .favnote");


// Clear all classes but .favnote
// Clear all classes but .favnote
favnoteEl.className = "favnote";
favnoteEl.className = "favnote";


// Add status
// Add status
favnoteEl.classList.add(status);
favnoteEl.classList.add(status);
}
}


// FavNote click event handler
// FavNote click event handler
function favnoteClick() {
function favnoteClick() {
var favnoteEl = this;
var favnoteEl = this;
var editorEl = document.querySelector("#gdf > .favnote + .editor");
var editorEl = document.querySelector("#gdf > .favnote + .editor");
var inputEl = document.querySelector("#gdf > .favnote + .editor > input");
var inputEl = document.querySelector("#gdf > .favnote + .editor > input");


// Determine mode
// Determine mode
var mode;
var mode;
if ( favnoteEl.classList.length === 1 ) mode = "show";
if ( favnoteEl.classList.length === 1 ) mode = "show";
else if ( favnoteEl.classList.contains("arrow") ) mode = "save";
else if ( favnoteEl.classList.contains("arrow") ) mode = "save";
else if ( favnoteEl.classList.contains("exclamation") ) mode = "reload";
else if ( favnoteEl.classList.contains("exclamation") ) mode = "reload";
else mode = "edit";
else mode = "edit";


// Behave accordingly
// Behave accordingly
switch(mode) {
switch(mode) {
case "show":
case "show":
updateFavnoteIcon("pencil"); // marks the next action to edit
updateFavnoteIcon("pencil"); // marks the next action to edit
editorEl.classList.add("show");
editorEl.classList.add("show");
inputEl.classList.add("notinput");
inputEl.classList.add("notinput");
break;
break;
case "edit":
case "edit":
updateFavnoteIcon("arrow"); // marks the next action to save
updateFavnoteIcon("arrow"); // marks the next action to save
editorEl.classList.add("show");
editorEl.classList.add("show");
inputEl.classList.remove("notinput");
inputEl.classList.remove("notinput");
break;
break;
case "save":
case "save":
var favID = getPageFavId();
var favID = getPageFavId();
quickFavourite(favID);
quickFavourite(favID);
break;
break;
case "reload":
case "reload":
// an error occurred, attempt to reload favnotes
// an error occurred, attempt to reload favnotes
document.querySelector(".favnote").remove();
document.querySelector(".favnote").remove();
document.querySelector(".editor").remove();
document.querySelector(".editor").remove();
injectFavnoteElements();
injectFavnoteElements();
break;
break;
default:
default:
dlog("What is happening?");
dlog("What is happening?");
alert("A really strange error occurred. This part of code should be reached.");
alert("A really strange error occurred. This part of code should be reached.");
return;
return;
}
}
}
}




/* ========================================================================= *\
/* ========================================================================= *\
* * FAVOURITE HOTKEYS
* * FAVOURITE HOTKEYS
\* ========================================================================= */
\* ========================================================================= */
// Adds keypress event listener
// Adds keypress event listener
function injectHotkeyListener() {
function injectHotkeyListener() {
document.addEventListener("keypress", hotkeyHandler);
document.addEventListener("keypress", hotkeyHandler);
dlog("Listening to keypress events now");
dlog("Listening to keypress events now");
}
}


// Handles keypresses
// Handles keypresses
function hotkeyHandler(e) {
function hotkeyHandler(e) {
let key = e.which;
let key = e.which;
let char = String.fromCharCode(key);
let char = String.fromCharCode(key);
if (hotkeyInit) {
if (hotkeyInit) {
if (e.keyCode == 27) {
if (e.keyCode == 27) {
return;
return;
}
}


// 0-9 and "-"
// 0-9 and "-"
let favID;
let favID;
switch(char) {
switch(char) {
case("0"):
case("0"):
favID = 0;
favID = 0;
break;
break;
case("1"):
case("1"):
favID = 1;
favID = 1;
break;
break;
case("2"):
case("2"):
favID = 2;
favID = 2;
break;
break;
case("3"):
case("3"):
favID = 3;
favID = 3;
break;
break;
case("4"):
case("4"):
favID = 4;
favID = 4;
break;
break;
case("5"):
case("5"):
favID = 5;
favID = 5;
break;
break;
case("6"):
case("6"):
favID = 6;
favID = 6;
break;
break;
case("7"):
case("7"):
favID = 7;
favID = 7;
break;
break;
case("8"):
case("8"):
favID = 8;
favID = 8;
break;
break;
case("9"):
case("9"):
favID = 9;
favID = 9;
break;
break;
case("-"):
case("-"):
favID = "favdel";
favID = "favdel";
break;
break;
default:
default:
disableHotkeys();
disableHotkeys();
break;
break;
}
}
if (typeof favID != "undefined") quickFavourite(favID);
if (typeof favID != "undefined") quickFavourite(favID);
} else {
} else {
if (char == "F") enableHotkeys();
if (char == "F") enableHotkeys();
}
}
}
}


function enableHotkeys() {
function enableHotkeys() {
hotkeyInit = true;
hotkeyInit = true;
if(config.cheatsheet) showCheatSheet();
if(config.cheatsheet) showCheatSheet();
dlog("Entering active hotkey favouriting mode");
dlog("Entering active hotkey favouriting mode");
}
}


function disableHotkeys() {
function disableHotkeys() {
if(config.cheatsheet) hideCheatSheet();
if(config.cheatsheet) hideCheatSheet();
hotkeyInit = false;
hotkeyInit = false;
dlog("Quitting active hotkey favouriting mode");
dlog("Quitting active hotkey favouriting mode");
}
}


function showCheatSheet() {
function showCheatSheet() {
dlog("Showing Cheat Sheet");
dlog("Showing Cheat Sheet");
document.getElementById("gdf").classList.add("hover");
document.getElementById("gdf").classList.add("hover");
}
}


function hideCheatSheet() {
function hideCheatSheet() {
dlog("Hiding Cheat Sheet");
dlog("Hiding Cheat Sheet");
document.getElementById("gdf").classList.remove("hover");
document.getElementById("gdf").classList.remove("hover");
}
}




/* ========================================================================= *\
/* ========================================================================= *\
* * CORE LOGICS
* * CORE LOGICS
\* ========================================================================= */
\* ========================================================================= */
function checkSyncNecessity() {
function checkSyncNecessity() {
// >1w = stale
// >1w = stale
let currentTime = new Date().getTime();
let currentTime = new Date().getTime();
let lastSyncTime = localStorage.getItem("EHGQF-lastSyncTime");
let lastSyncTime = localStorage.getItem("EHGQF-lastSyncTime");
let timeDelta = currentTime - lastSyncTime;
let timeDelta = currentTime - lastSyncTime;
if ( timeDelta > 1000*60*60*24*7 ) return true;
if ( timeDelta > 1000*60*60*24*7 ) return true;


// setup
// setup
let x = localStorage.getItem("EHGQF-setup");
let x = localStorage.getItem("EHGQF-setup");
if (typeof x == "undefined") return true;
if (typeof x == "undefined") return true;


// constant page check
// constant page check
let labelId = getPageFavId();
let labelId = getPageFavId();
if ( labelId == 10 ) return false; // can't check if page isn't favourited yet
if ( labelId == 10 ) return false; // can't check if page isn't favourited yet


let pageLabel = document.querySelector("#favoritelink").textContent;
let pageLabel = document.querySelector("#favoritelink").textContent;
let storedLabel = localStorage.getItem(`EHGQF-fav${labelId}`);
let storedLabel = localStorage.getItem(`EHGQF-fav${labelId}`);
if ( pageLabel != storedLabel ) return true;
if ( pageLabel != storedLabel ) return true;


dlog("No reason found to sync favourite labels");
dlog("No reason found to sync favourite labels");
return false;
return false;
}
}


function syncFavouriteLabels() {
function syncFavouriteLabels() {
dlog("Fetching fresh Favourite Labels!");
dlog("Fetching fresh Favourite Labels!");


// Send XHR to Favourite Page
// Send XHR to Favourite Page
var galID = location.pathname.match(/^\/\w\/(\d+)\//)[1];
var galID = location.pathname.match(/^\/\w\/(\d+)\//)[1];
var token = location.pathname.match(/\/(\w+)\/$/)[1];
var token = location.pathname.match(/\/(\w+)\/$/)[1];
var prot = location.protocol;
var prot = location.protocol;
var host = location.host;
var host = location.host;
var url = `${prot}//${host}/gallerypopups.php?gid=${galID}&t=${token}&act=addfav`;
var url = `${prot}//${host}/gallerypopups.php?gid=${galID}&t=${token}&act=addfav`;


var xhr = new XMLHttpRequest();
GM.xmlHttpRequest({
xhr.open("GET", url, true);
method: "GET",
xhr.responseType = "document";
url: url,
xhr.send();
onload: function(response) {

const responseXML = new DOMParser().parseFromString(response.responseText, "text/xml");
// And grab the favnotes
xhr.onreadystatechange = function() {
for(let i=0; i<=9; i++) {
if ( xhr.readyState == 4 && xhr.status == 200 ) {
let label = responseXML.querySelector(`div + div + div[onclick*='fav${i}']`).textContent;
let data = xhr.response;
localStorage.setItem(`EHGQF-fav${i}`, label);
for(let i=0; i<=9; i++) {
let label = data.querySelector(`div + div + div[onclick*='fav${i}']`).textContent;
localStorage.setItem(`EHGQF-fav${i}`, label);
}
dlog("Favourite Labels Updated!");
let time = new Date().getTime();
localStorage.setItem("EHGQF-setup", 1);
localStorage.setItem("EHGQF-lastSyncTime", time);
updateCurrentFav();
injectQFElements();
}
}
};
dlog("Favourite Labels Updated!");
let time = new Date().getTime();
localStorage.setItem("EHGQF-setup", 1);
localStorage.setItem("EHGQF-lastSyncTime", time);
updateCurrentFav();
injectQFElements();
}
});
}
}


function init() {
function init() {
dlog("Initialization start!");
dlog("Initialization start!");
if ( checkSyncNecessity() ) syncFavouriteLabels();
if ( checkSyncNecessity() ) syncFavouriteLabels();
injectStylesheet();
injectStylesheet();
injectQFElements();
injectQFElements();
injectFavnoteElements();
injectFavnoteElements();
if (config.hotkeys) injectHotkeyListener();
if (config.hotkeys) injectHotkeyListener();


dlog("Initialization finished!");
dlog("Initialization finished!");
}
}


init();
init();