// ==UserScript== // @name ppixiv for Pixiv // @author ppixiv // @description Better Pixiv viewing | Fullscreen images | Faster searching | Bigger thumbnails | Download ugoira MKV | Ugoira seek bar | Download manga ZIP | One-click like, bookmark, follow | One-click zoom and pan | Light and dark themes // @include http://*.pixiv.net/* // @include https://*.pixiv.net/* // @run-at document-start // @grant GM.xmlHttpRequest // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @connect pixiv.net // @connect i.pximg.net // @connect self // @namespace ppixiv // @version 119 // @downloadURL none // ==/UserScript== (function() { const ppixiv = this; with(this) { ppixiv.resources = {}; ppixiv.resources["resources/activate-icon.png"] = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAsCAYAAAAacYo8AAAACXBIWXMAAC4jAAAuIwF4pT92AAAGU2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAxOC0wNi0yN1QwMjoyMjoyOS0wNTowMCIgeG1wOk1vZGlmeURhdGU9IjIwMTgtMDYtMjdUMDI6MjY6MjAtMDU6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMTgtMDYtMjdUMDI6MjY6MjAtMDU6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MWU4MmI3MjgtOTVjNi1mNzQyLWJjOWQtMjIwMTM5NzJkNDBlIiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6N2ZkYzUwY2ItYjgzMy1hNzQzLTllMjYtNzQ1NmM4NDFlNjM0IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MzMyMzRmNjktNjk2OS1jNjQ1LWI0MjgtYmM1NDUwYTM3NDAzIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDozMzIzNGY2OS02OTY5LWM2NDUtYjQyOC1iYzU0NTBhMzc0MDMiIHN0RXZ0OndoZW49IjIwMTgtMDYtMjdUMDI6MjI6MjktMDU6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNvbnZlcnRlZCIgc3RFdnQ6cGFyYW1ldGVycz0iZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL3BuZyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MWU4MmI3MjgtOTVjNi1mNzQyLWJjOWQtMjIwMTM5NzJkNDBlIiBzdEV2dDp3aGVuPSIyMDE4LTA2LTI3VDAyOjI2OjIwLTA1OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmQ/KUAAAAQhSURBVFiF7ZlNTxtHGMd/s/aaGGqDHRRLwQergko+lJhW4pJDqdQLpzSfoOHqU/sJGj5By8VXkk8QcuqlUtxjckBWLxxaqVYFVQnCdWiDYy/e6WG8Zr07a68X8xIpfwmtZp6Z2d8+fuaZF4SUkvdRxnUDRNV7Cx4HEEJMbsRKpwTMAc7TUb3316ScqEUd3gltIaW8GHil8zXwBbCGgg2rKvAc2KGcqIftdDHwSmcN+AZ4NF7HQO0AW5QT1VENo4FXOo+A74GCzizaDWg3EN1TOGsNGuNJZOI2cioL8eSwD9ignGhOBnwIsGgdIt4dIlqvwbaGj+O8fCqLTC+pj/Cr2YPfiQ6uJtoPqPj1ARtv9vyeHUMymcPOfAqGqTNvUE488fUZCV7pPEZ52SfRbmAcvYwMPKB4Evv2Z0gzrbP64IPBK5054BkaLzsKAy6TOWR60Qek7WuYdO/cD4r9FXf6dMDjA01UaLxgMP82PeXhwDML2JnlfvnjuzESpqBjSQ6ObNpk6ebXVagd76pGtoVxvIudu68bchtY8Vaer5xqAnqha8BGWOhufh07s0wmZbBaNFktmszPGqSnBfOzBvcW46wWVTzLZA45s9DvK6wTxH913bClHpsGXBm2PdA7lBMrKI8PB777Fd38er+8lI8Nbe/A25nlAS8bJ78HdfHNNcfj2576GiE93c2vg2EiWodhmvf1+Sc9z7vngG0h3h7omhd6K3RfDvimq64JPBy2CPjUi9FxFHP9KO45Id4FOuCBu+CA/4jaAAFUx9k7GEcvEda/YZtrNRDr7UZQs9LAewF63nVCY26cl040p4NaffUrcMldOM8qaoOzCTydHEVIeVbfML/gYB4vJx5PkiesjDd74RqqdaYG13gCerWnwkG0G+EzkmsFvRZwBxrb0s4PaaZGjhEf2SKCXu1ZTN8SLMwbZFLnvvnzsMvfDbtfjv31s7+zYQbtFuvuwqWAG//8yulskd/2TaDrtx/vBoaHTN4JGrbqLlwKuHh7QEy/Ao6UnM4HmZ67CzfqekJOZYNORXXviehSwN0brnEk54pBpk1vxURDJbb/U+S+dmY56BRU1R3hbkSoyI8KA/sVl5rAQ53hUiZnaBkm9mxxGPSXQbvUSODSTGGnlzBO9yOf8uXMAnZqKeicWUdtrWtB/aN53DCR6UW66UWEdQKt1+p51lLPINiprDqy3cpd6FIoOrgbxkyDmcZ7yy6sE7DPem1SQauhW3Xgu6CLIK+igteALdSpZA3NHj4gQ+i0AzwNC+woKnizl6KeAM4laAm4h7qmK6E/kDRRH10DfkGlumYUgMlkFXUIqU5krJC6EXk8ij6AX7WGg6sL0AcaS6E3Ia9Nozz+B/Ctpr4AvKDS0dmuRKOyytYIe21CHGNLfPjP8hXrf5SZd4NRInfBAAAAAElFTkSuQmCC`; ppixiv.resources["resources/checkbox.svg"] = ` `; ppixiv.resources["resources/close-button.svg"] = ` `; ppixiv.resources["resources/disabled.html"] = `
`; ppixiv.resources["resources/download-icon.svg"] = ` `; ppixiv.resources["resources/download-manga-icon.svg"] = ` `; ppixiv.resources["resources/edit-icon.svg"] = ``; ppixiv.resources["resources/exit-icon.svg"] = ` `; ppixiv.resources["resources/eye-icon.svg"] = ` `; ppixiv.resources["resources/favorited-icon.png"] = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGbWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAxOC0wNi0yMFQwMDo1NjoyOS0wNTowMCIgeG1wOk1vZGlmeURhdGU9IjIwMTgtMDYtMjBUMDE6MjM6NTktMDU6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMTgtMDYtMjBUMDE6MjM6NTktMDU6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTFkYzgwNjgtMDM1Ny0xNzRlLTlmMDAtNThjYjk4NTQ4OWQ2IiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6NzdlYmJlZGEtYjQ4Yy0yYzRkLTk2MTQtYmM3NmZmN2VjYTU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ZDFkMGQ2NzQtMTBkNC00MDQ1LTliZGQtNTY2ZDYxZTNlYTU0Ij4gPHBob3Rvc2hvcDpUZXh0TGF5ZXJzPiA8cmRmOkJhZz4gPHJkZjpsaSBwaG90b3Nob3A6TGF5ZXJOYW1lPSLimIUiIHBob3Rvc2hvcDpMYXllclRleHQ9IuKYhSIvPiA8L3JkZjpCYWc+IDwvcGhvdG9zaG9wOlRleHRMYXllcnM+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ZDFkMGQ2NzQtMTBkNC00MDQ1LTliZGQtNTY2ZDYxZTNlYTU0IiBzdEV2dDp3aGVuPSIyMDE4LTA2LTIwVDAwOjU2OjI5LTA1OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxMWRjODA2OC0wMzU3LTE3NGUtOWYwMC01OGNiOTg1NDg5ZDYiIHN0RXZ0OndoZW49IjIwMTgtMDYtMjBUMDE6MjM6NTktMDU6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+LpZUDAAABwxJREFUeJzlm29sG2cdxz93tnOOHedP4yZuq7QpibsSBeKWsVWZyqAQaWKTJmBVEjQoSBOVKAiYqkkVlYbGEO94AWKiiGkvOmnrRMUfsSpNUatVtEQg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`; ppixiv.resources["resources/followed-users-eye.svg"] = ` `; ppixiv.resources["resources/fullscreen.svg"] = ` `; ppixiv.resources["resources/heart-icon.svg"] = ` `; ppixiv.resources["resources/icon-bookmarks.svg"] = ` `; ppixiv.resources["resources/icon-circlems.svg"] = ` `; ppixiv.resources["resources/icon-pawoo.svg"] = ` `; ppixiv.resources["resources/icon-search.svg"] = ` `; ppixiv.resources["resources/icon-twitter.svg"] = ` `; ppixiv.resources["resources/icon-webpage.svg"] = ` `; ppixiv.resources["resources/last-page.svg"] = ` `; ppixiv.resources["resources/last-viewed-image-marker.svg"] = ` `; ppixiv.resources["resources/like-button.svg"] = ` `; ppixiv.resources["resources/link-icon.svg"] = ` `; ppixiv.resources["resources/main.html"] = ` `; ppixiv.resources["resources/main.scss"] = `/* line 1, resources/main.scss */ * { box-sizing: border-box; } /* line 2, resources/main.scss */ html { overflow: hidden; } /* line 5, resources/main.scss */ body { font-family: "Helvetica Neue", arial, sans-serif; } /* line 9, resources/main.scss */ a { text-decoration: none; /*color: #fff;*/ color: inherit; } /* Theme colors: */ /* line 16, resources/main.scss */ body { --button-color: #888; --button-highlight-color: #eee; /* Colors for major UI boxes */ --ui-bg-color: #222; --ui-fg-color: #fff; --ui-border-color: #000; --ui-shadow-color: #000; /* the shadow around some major UI elements */ --ui-bg-section-color: #555; /* color for sections within UI, like the description box */ --toggle-button-fg-disabled-color: #666; --toggle-button-fg-dim-color: #888; --toggle-button-fg-color: #fff; --toggle-button-bg-dim-color: #222; --toggle-button-bg-color: #444; /* Color for frames like popup menus */ --frame-bg-color: #000; --frame-fg-color: #fff; --frame-border-color: #444; --dropdown-menu-hover-color: #444; /* Box links used for selection in the search UI: */ --box-link-fg-color: var(--frame-fg-color); --box-link-bg-color: var(--frame-bg-color); --box-link-disabled-color: #888; --box-link-hover-color: #443; --box-link-selected-color: #008; /* Color for the minor text style, eg. the bookmark and like counts. * This is smaller text, with a text border applied to make it readable. */ --minor-text-fg-color: #aaa; --minor-text-shadow-color: #000; --title-fg-color: #fff; /* title strip in image-ui */ --title-bg-color: #444; --like-button-color: #888; --like-button-liked-color: #ccc; --like-button-hover-color: #fff; } /* line 60, resources/main.scss */ body.light { --ui-bg-color: #eee; --ui-fg-color: #222; --ui-border-color: #ccc; --ui-shadow-color: #fff; --ui-bg-section-color: #ccc; /* color for subsections */ --button-color: #666; --button-highlight-color: #222; --toggle-button-fg-dim-color: #222; --toggle-button-fg-color: #000; --toggle-button-bg-dim-color: #eee; --toggle-button-bg-color: #ccc; --frame-bg-color: #fff; --frame-fg-color: #222; --dropdown-menu-hover-color: #ccc; --box-link-hover-color: #ddc; --box-link-selected-color: #ffc; --minor-text-fg-color: #555; /* 555 */ --minor-text-shadow-color: #fff; /* fff */ --title-fg-color: #fff; --title-bg-color: #888; --like-button-liked-color: #222; --like-button-hover-color: #000; } /* line 92, resources/main.scss */ ul { padding: 0; margin: 0; } /* line 96, resources/main.scss */ .screen:focus { /* Views have tabindex: -1 set. This causes Chrome to put a blue outline around them * when they're focused, which just puts a weird border around the whole window. Remove * it. */ outline: none; } /* line 102, resources/main.scss */ .screen-illust-container { width: 100%; height: 100%; } /* line 107, resources/main.scss */ .image-container, .preview-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; user-select: none; cursor: pointer; } /* Let the browser know about our dynamic zooming and panning. This prevents Chrome from baking the * resize when it doesn't change for a while, which causes a big hitch the next time we zoom. */ /* line 119, resources/main.scss */ .image-container > img { will-change: transform; } /* line 127, resources/main.scss */ [hidden] { display: none !important; } /* line 131, resources/main.scss */ textarea:focus, input:focus, a:focus { outline: none; } /* Pixiv sometimes displays a random Recaptcha icon in the corner. It's hard to prevent this since it * sometimes loads before we have a chance to stop it. Try to hide it. */ /* line 137, resources/main.scss */ .grecaptcha-badge { display: none !important; } /* line 141, resources/main.scss */ .main-container { position: fixed; top: 0px; left: 0px; width: 100%; height: 100%; overflow: hidden; } /* line 149, resources/main.scss */ .progress-bar { position: absolute; pointer-events: none; background-color: #F00; bottom: 0px; left: 0px; width: 100%; height: 2px; } @keyframes flash-progress-bar { to { opacity: 0; } } /* line 159, resources/main.scss */ .progress-bar.hide { animation: flash-progress-bar 500ms linear 1 forwards; } /* line 163, resources/main.scss */ .loading-progress-bar .progress-bar { z-index: 100; } /* .seek-bar is the outer seek bar area, which is what can be dragged. */ /* line 168, resources/main.scss */ .seek-bar { position: absolute; bottom: 0px; left: 0px; width: 100%; box-sizing: content-box; height: 12px; padding-top: 25px; cursor: pointer; /* Hide the seek bar by default (move down by 12px). Show it when the mouse is visible * or .visible is set (move down by 6px). Expand it while dragging (0px). */ } /* line 180, resources/main.scss */ .seek-bar .seek-empty { height: 100%; background-color: rgba(0, 0, 0, 0.25); } /* line 185, resources/main.scss */ .seek-bar .seek-fill { background-color: #F00; height: 100%; } /* line 190, resources/main.scss */ .seek-bar .seek-empty { transition: transform .25s; transform: translate(0, 12px); } /* line 197, resources/main.scss */ .mouse-hidden-box.show-cursor .seek-bar .seek-empty, .seek-bar.visible .seek-empty { transform: translate(0, 6px); } /* line 203, resources/main.scss */ .seek-bar.dragging .seek-empty { transform: translate(0, 0); } /* line 208, resources/main.scss */ .title-font { font-weight: 700; font-size: 20px; font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Droid Sans, Helvetica Neue, Hiragino Kaku Gothic ProN, Meiryo, sans-serif; } /* line 215, resources/main.scss */ .small-font { font-size: 0.8em; } /* line 219, resources/main.scss */ .hover-message, .search-results > .no-results { width: 100%; position: absolute; bottom: 0px; display: flex; justify-content: center; } /* line 227, resources/main.scss */ .hover-message > .message, .search-results > .no-results > .message { background-color: var(--frame-bg-color); color: var(--frame-fg-color); font-size: 1.4em; padding: 6px 15px; margin: 4px; max-width: 600px; text-align: center; border-radius: 5px; box-shadow: 0 0 10px 5px #aaa; } /* line 240, resources/main.scss */ .hover-message { transition: opacity .25s; opacity: 0; pointer-events: none; z-index: 100; } /* line 246, resources/main.scss */ .hover-message.show { opacity: 1; } /* The version in the search container is always centered. */ /* line 252, resources/main.scss */ .search-results > .no-results { bottom: 50%; } /* line 257, resources/main.scss */ .screen-illust-container .ui { position: absolute; top: 0px; left: 0px; min-width: 450px; max-height: 500px; width: 30%; height: auto; /* Disable events on the top-level container, so it doesn't block clicks on the * image when the UI isn't visible. We'll reenable events on the hover-box and ui-box * below it where we actually want pointer events. */ pointer-events: none; } /* line 271, resources/main.scss */ .screen-illust-container .ui .disabled { display: none; } /* * This is the box that triggers the UI to be displayed. We use this rather than * ui-box for this so we can give it a fixed size. That way, the UI box won't suddenly * appear when changing to another image because a longer description caused the box * to become bigger. * * This is a little tricky. Hovering over either hover-box or the UI makes it visible. * When the UI is hidden, it's set to pointer-events: none, so it can't be hovered, * but once you hover over hover-box and cause the UI to be visible, pointer events * are reenabled so hovering over anywhere in the UI keeps it visible. The UI is * over hover-box in the Z order, so we don't need to disable pointer events on hover-box * to prevent it from blocking the UI. * * We also disable pointer-events on the UI until it's visible, so it doesn't receive * clicks until it's visible. */ /* line 293, resources/main.scss */ .hover-box { width: 400px; height: 200px; position: absolute; top: 0; left: 0; pointer-events: auto; /* reenable pointer events that are disabled on .ui */ } /* line 302, resources/main.scss */ .hover-sphere { width: 500px; height: 500px; /* Clamp the sphere to a percentage of the viewport width, so it gets smaller for * small windows. */ max-width: 30vw; max-height: 30vw; position: absolute; top: 0; left: 0; } /* line 314, resources/main.scss */ .hover-sphere circle { pointer-events: auto; /* reenable pointer events that are disabled on .ui */ } /* line 318, resources/main.scss */ .hover-sphere > svg { width: 100%; height: 100%; transform: translate(-50%, -50%); } /* line 325, resources/main.scss */ .screen-manga-container .ui-container { width: 600px; max-width: 90%; pointer-events: auto; } /* line 331, resources/main.scss */ .ui-box { background-color: var(--ui-bg-color); color: var(--ui-fg-color); border: solid 2px var(--ui-border-color); padding: 1em; border-radius: 8px; position: relative; /* Since the UI isn't a popup on the manga page, hide the description and * tag list to make it smaller. These can be viewed while viewing a page. */ } /* line 340, resources/main.scss */ .ui-box .author { vertical-align: top; } /* line 345, resources/main.scss */ .ui-box:not(.visible-widget) { display: inherit !important; } /* line 350, resources/main.scss */ .screen-illust-container .ui-box { transition: transform .25s, opacity .25s; opacity: 0; transform: translate(-50px, 0); pointer-events: none; margin: .5em; /* Show the UI on hover when hide-ui isn't set. */ /* Debugging: */ } /* line 359, resources/main.scss */ body:not(.hide-ui) .screen-illust-container .ui-box.visible-widget { opacity: 1; transform: translate(0, 0); pointer-events: auto; } /* line 368, resources/main.scss */ body.force-ui .screen-illust-container .ui-box { opacity: 1; transform: translate(0, 0); pointer-events: inherit; } /* line 379, resources/main.scss */ .screen-manga-container .ui-box > .description, .screen-manga-container .ui-box > .tag-list { display: none; } /* line 386, resources/main.scss */ .ui-box .button > svg { display: block; } /* line 390, resources/main.scss */ .ui-box .button.button-bookmark .count, .ui-box .button.button-like .count { top: calc(100% - 11px); left: calc(-50px + 50%); width: 100px; pointer-events: none; } /* line 400, resources/main.scss */ .button-row { display: flex; flex-direction: row; align-items: center; height: 32px; margin-top: 5px; margin-bottom: 4px; } /* line 408, resources/main.scss */ .button-row .button.enabled { cursor: pointer; } /* The row with the search title, with buttons aligned to the right. The buttons * are always aligned to the top if the title is long. */ /* line 415, resources/main.scss */ .title-with-button-row { display: flex; flex-direction: row; align-items: start; } /* An icon in a button strip. */ /* line 422, resources/main.scss */ .icon-button { display: block; width: 32px; height: auto; /* If this is an icon-button with an svg inside, set the svg to block. */ } /* line 428, resources/main.scss */ .icon-button svg { display: block; } /* line 433, resources/main.scss */ .disable-ui-button:hover > .icon-button { color: #0096FA; } /* line 436, resources/main.scss */ .whats-new-button.updates > svg { color: #cc0; } /* line 439, resources/main.scss */ body.light .whats-new-button.updates > svg { color: #0aa; /* yellow doesn't work in a light theme */ } /* line 443, resources/main.scss */ .navigate-out-button { cursor: pointer; } /* line 447, resources/main.scss */ .menu-slider input { vertical-align: middle; width: 100%; padding: 0; margin: 0; } /* line 454, resources/main.scss */ .popup.avatar-popup:hover:after { left: auto; bottom: auto; top: 60px; right: -10px; } /* line 461, resources/main.scss */ .follow-container { /* For the avatar in the popup menu, use the same size as the other popup menu buttons. */ } /* line 462, resources/main.scss */ .follow-container .avatar { transition: filter .25s; display: block; position: relative; /* .avatar contains an image, and a canvas overlaid on top for hover effects. */ } /* line 468, resources/main.scss */ .follow-container .avatar > canvas { border-radius: 5px; object-fit: cover; width: 100%; height: 100%; position: absolute; top: 0; left: 0; } /* line 478, resources/main.scss */ .follow-container .avatar > canvas.highlight { opacity: 0; transition: opacity .25s; } /* line 483, resources/main.scss */ .follow-container .avatar:hover > canvas.highlight { opacity: 1; } /* line 488, resources/main.scss */ .follow-container:not(.big) .avatar { width: 50px; height: 50px; } /* line 493, resources/main.scss */ .follow-container.big .avatar { width: 170px; height: 170px; } /* line 499, resources/main.scss */ .avatar-widget-container .follow-container .avatar { width: 44px; height: 44px; } /* Hide the avatar while we're waiting for user data to load, since the follow icons aren't * updated until then. */ /* line 507, resources/main.scss */ .follow-container.loading { visibility: hidden; pointer-events: none; } /* The API doesn't tell us whether a follow is private or not, so we can't show * it. The lock is only used to distinguish the "follow" and "follow privately" * buttons. */ /* line 516, resources/main.scss */ .follow-icon .lock { stroke: #888; } /* line 520, resources/main.scss */ .follow-icon:not(.private) .lock { display: none !important; } /* line 525, resources/main.scss */ .follow-container { /* Hide the following icon if we're not following. */ /* Hide the follow buttons if we're already following. */ /* Only show the follow buttons on hover (but always show the following icon). */ /* If use-dropdown is set, this avatar is using the dropdown UI and doesn't show the * follow/unfollow overlay buttons. */ /* Don't show follow buttons or the follow popup for the user himself. */ /* In small avatar buttons, nudge the follow buttons down off of the * avatar, so they don't appear right under the cursor when you're trying * to click the avatar itself. Only do this with the follow buttons that * appears on hover, not the following icon (unfollow button), and don't * do it with the big avatars. */ /* Don't fade the icons in the context menu, since it's too small and it makes * it too hard to see at a glance. */ } /* line 526, resources/main.scss */ .follow-container .follow-icon { position: absolute; bottom: 0; text-align: center; height: auto; width: 50%; /* half the size of the container */ max-width: 50px; /* limit the size for larger avatar displays */ } /* line 534, resources/main.scss */ .follow-container .follow-icon.bottom-left { left: 0; } /* line 538, resources/main.scss */ .follow-container .follow-icon.bottom-right { right: 0; } /* line 543, resources/main.scss */ .follow-container .follow-icon:not(:hover) .outline1 { stroke: none !important; } /* line 548, resources/main.scss */ .follow-container:not(.followed) .follow-icon.following-icon { display: none; } /* line 553, resources/main.scss */ .follow-container.followed .follow-icon.follow-button { display: none; } /* line 558, resources/main.scss */ .follow-container:not(:hover) .follow-icon.follow-button { display: none; } /* line 564, resources/main.scss */ .follow-container[data-mode="dropdown"] .follow-icon.follow-button { display: none; } /* line 569, resources/main.scss */ .follow-container.self .follow-icon, .follow-container.self .follow-popup { display: none; } /* line 580, resources/main.scss */ .follow-container:not(.big) .follow-button { top: calc(100% - 5px); } /* line 584, resources/main.scss */ .follow-container .follow-icon > svg { display: block; width: 100%; height: auto; transition: opacity .25s; /* Move the icon down, so the bottom of the eye is along the bottom of the * container and the lock (if visible) overlaps. */ margin-bottom: -20%; } /* line 595, resources/main.scss */ .follow-container:not(:hover) .follow-icon > svg { opacity: 0.5; } /* line 601, resources/main.scss */ .popup-context-menu .follow-container .follow-icon > svg { opacity: 1; } /* line 605, resources/main.scss */ .follow-container .follow-icon > svg .middle { transition: transform .1s ease-in-out; transform: translate(0px, -2px); } /* line 610, resources/main.scss */ .follow-container .follow-icon.unfollow-button > svg .middle { transform: translate(-2px, -5px); } /* line 614, resources/main.scss */ .follow-container .follow-icon.unfollow-button:hover > svg .middle { transform: translate(2px, 5px); } /* line 618, resources/main.scss */ .follow-container .follow-popup { margin-top: 10px; right: 0px; } /* line 622, resources/main.scss */ .follow-container .follow-popup .folder { display: block; width: 100%; } /* line 627, resources/main.scss */ .follow-container.followed .follow-container .follow-popup .not-following { display: none; } /* line 628, resources/main.scss */ .follow-container:not(.followed) .follow-container .follow-popup .following { display: none; } /* line 630, resources/main.scss */ .follow-container .follow-popup input { padding: .25em; } /* line 635, resources/main.scss */ .follow-container .hover-area { top: -12px; } /* line 639, resources/main.scss */ .follow-container .avatar-link { display: block; } /* Hide the follow dropdown when following, since there's nothing in it. */ /* line 645, resources/main.scss */ .follow-container.followed.popup-visible .popup-menu-box.hover-menu-box { visibility: hidden; } /* line 649, resources/main.scss */ .title-block { display: inline-block; padding: 0 10px; color: var(--title-fg-color); background-color: var(--title-bg-color); margin-right: 1em; border-radius: 8px 0; } /* line 657, resources/main.scss */ .title-block.popup:hover:after { top: 40px; bottom: auto; } /* When .dot is set, show images with nearest neighbor filtering. */ /* line 664, resources/main.scss */ body.dot img.filtering, body.dot canvas.filtering { image-rendering: crisp-edges; image-rendering: pixelated; } /* line 669, resources/main.scss */ .bulb-button:hover > .icon-button { color: #FF0 !important; /* override grey-icon hover color */ } /* line 673, resources/main.scss */ body.light .bulb-button:hover > .icon-button { stroke: #000; } /* line 677, resources/main.scss */ .bulb-button > .icon-button { margin-top: -3px; } /* line 682, resources/main.scss */ .extra-profile-link-button .default-icon svg { transform: translate(0, 2px); } /* line 687, resources/main.scss */ .post-info > * { display: inline-block; background-color: var(--box-link-bg-color); color: var(--box-link-fg-color); padding: 2px 10px; /* Use a smaller, heavier font to distinguish these from tags. */ font-size: .8em; font-weight: bold; } /* line 697, resources/main.scss */ .description { border: solid 1px var(--ui-border-color); padding: .35em; background-color: var(--ui-bg-section-color); max-height: 10em; overflow-y: auto; } /* line 704, resources/main.scss */ body.light .description { border: none; } /* Override obnoxious colors in descriptions. Why would you allow this? */ /* line 708, resources/main.scss */ .description * { color: var(--ui-fg-color); } /* line 712, resources/main.scss */ .popup { position: relative; } /* line 716, resources/main.scss */ .popup:hover:after { pointer-events: none; background: #111; border-radius: .5em; left: 0em; top: -2.0em; color: #fff; content: attr(data-popup); display: block; padding: .3em 1em; position: absolute; text-shadow: 0 1px 0 #000; white-space: nowrap; z-index: 98; } /* line 731, resources/main.scss */ .popup-bottom:hover:after { top: auto; bottom: -2em; } /* line 736, resources/main.scss */ body:not(.premium) .premium-only { display: none; } /* line 737, resources/main.scss */ body.hide-r18 .r18 { display: none; } /* line 738, resources/main.scss */ body.hide-r18g .r18g { display: none; } /* line 740, resources/main.scss */ .popup-menu-box { position: absolute; left: 0; top: 100%; min-width: 10em; background-color: var(--frame-bg-color); border: 1px solid var(--frame-border-color); padding: .25em .5em; z-index: 2; } /* line 751, resources/main.scss */ .popup-menu-box.hover-menu-box { visibility: hidden; } /* line 754, resources/main.scss */ .popup-visible .popup-menu-box.hover-menu-box { visibility: inherit; } /* This is an invisible block underneath the hover zone to keep the hover UI visible. */ /* line 759, resources/main.scss */ .hover-area { position: absolute; top: -50%; left: -33%; width: 150%; height: 200%; z-index: -1; } /* line 768, resources/main.scss */ .popup-menu-box .button { padding: .25em; cursor: pointer; width: 100%; } /* line 775, resources/main.scss */ .popup-menu-box .button:hover { background-color: var(--dropdown-menu-hover-color); } /* line 779, resources/main.scss */ .top-ui-box { /* This places the thumbnail UI at the top, so the thumbnails sit below it when * scrolled all the way up, and scroll underneath it. */ position: sticky; top: 0; width: 100%; display: flex; flex-direction: row; align-items: center; padding-top: 1em; padding-bottom: .5em; z-index: 1; /* Prevent the empty space around the UI for centering from eating button presses. */ pointer-events: none; /* If .ui-on-hover is set, switch to showing the top UI when it's hovered instead of sticky. */ /* This is used to temporarily disable the transition when the ui-on-hover setting is * changed in the options menu. */ } /* line 797, resources/main.scss */ body.ui-on-hover .top-ui-box { position: fixed; top: auto; bottom: 100%; transition: transform ease-out .2s; /* Normally pointer-events is disabled above, so the sides of the UI box don't cover clicks. * However, that also makes the hover not include the top padding above the UI, causing it * to flicker on and off when the mouse is in that area. This is tricky to fix nicely, so just * stop disabling pointer-events when ui-on-hover is enabled. */ pointer-events: auto; } /* line 813, resources/main.scss */ body.ui-on-hover .top-ui-box.disable-transition { transition: none; } /* .force-open is set to lock the UI in place when a menu is open. It has the same * effect as a hover. */ /* line 821, resources/main.scss */ body.ui-on-hover .top-ui-box.hover, body.ui-on-hover .top-ui-box.force-open { transform: translateY(100%); } /* line 827, resources/main.scss */ body.ui-on-hover .top-ui-box:not(.hover):not(.force-open) { /* This is the amount the UI pokes on-screen when not hovered. */ transform: translateY(40px); } /* When ui-on-hover is disabled we get spacing at the top of the thumbs automatically from * position: sticky, but ui-on-hover is position: fixed and we don't get that, so we have * to add padding manually. */ /* line 836, resources/main.scss */ body.ui-on-hover .top-ui-box + .top-ui-box-padding { height: 30px; } /* Search result views. This is used for both the search view and the manga page list. */ /* line 842, resources/main.scss */ .search-results { position: absolute; width: 100%; height: 100%; top: 0; left: 0; overflow-x: hidden; /* Always show the vertical scrollbar, so we don't relayout as images load. */ overflow-y: scroll; color: #fff; /* .thumbnails is the actual thumbnail list. */ } /* line 853, resources/main.scss */ .search-results .thumbnail-ui-box { width: 50%; /* Make sure this doesn't get too narrow, or it'll overlap too much of the thumbnail area. */ min-width: 800px; background-color: var(--ui-bg-color); color: var(--ui-fg-color); box-shadow: 0 0 15px 10px var(--ui-shadow-color); border-radius: 4px; padding: 10px; pointer-events: auto; } /* line 865, resources/main.scss */ .search-results .thumbnail-ui-box .disable-ui-button { margin-right: 2px; } /* line 868, resources/main.scss */ .search-results .thumbnail-ui-box .disable-ui-button > svg { width: 22px; } /* line 873, resources/main.scss */ .search-results .thumbnail-ui-box .displaying { padding-bottom: 4px; } /* line 876, resources/main.scss */ .search-results .thumbnail-ui-box .displaying .word { padding: 0px 5px; } /* line 880, resources/main.scss */ .search-results .thumbnail-ui-box .displaying .word:first-child { padding-left: 0px; /* remove left padding from the first item */ } /* line 884, resources/main.scss */ .search-results .thumbnail-ui-box .displaying .word.or { font-size: 12px; padding: 0; color: #bbb; } /* line 890, resources/main.scss */ .search-results .thumbnail-ui-box .bookmarks-link > svg, .search-results .thumbnail-ui-box .following-link > svg { width: 32px; height: 32px; } /* line 896, resources/main.scss */ .search-results .thumbnail-ui-box .contact-link > svg { width: 31px; height: 31px; margin: 0 3px; } /* line 902, resources/main.scss */ .search-results .thumbnail-ui-box .webpage-link > svg { margin: 0 2px; width: 26px; height: 26px; } /* line 908, resources/main.scss */ .search-results .thumbnail-ui-box .circlems-icon > svg { margin: 2px 0 0 0; } /* line 914, resources/main.scss */ .search-results .thumbnails { user-select: none; padding: 0; text-align: center; } /* line 920, resources/main.scss */ .search-results .thumbnails { display: flex; flex-wrap: wrap; justify-content: center; margin: 0 auto; /* center */ } /* line 930, resources/main.scss */ .search-results .flash a { animation-name: flash-thumbnail; animation-duration: 300ms; animation-timing-function: ease-out; animation-iteration-count: 1; } @keyframes flash-thumbnail { 0% { filter: brightness(200%); } } /* line 944, resources/main.scss */ .search-results .last-viewed-image-marker { position: absolute; left: 0; top: 0; pointer-events: none; height: auto; } /* line 954, resources/main.scss */ .search-results .thumbnail-box:not(.flash) .last-viewed-image-marker { display: none; } /* line 959, resources/main.scss */ .thumbnail-load-previous { width: 100%; } /* line 962, resources/main.scss */ .thumbnail-load-previous > .load-previous-buttons { margin-left: auto; margin-right: auto; display: flex; flex-direction: row; margin-top: 10px; margin-bottom: 4px; justify-content: center; height: 40px; max-width: 800px; } /* line 973, resources/main.scss */ .thumbnail-load-previous > .load-previous-buttons > .load-previous-button { display: flex; flex-direction: column; align-items: center; justify-content: center; flex-grow: 1; margin: 0 10px; background-color: #880; border-radius: 4px; padding: 0 10px; color: var(--box-link-fg-color); background-color: var(--box-link-bg-color); } /* line 986, resources/main.scss */ .thumbnail-load-previous > .load-previous-buttons > .load-previous-button:hover { background-color: var(--box-link-hover-color); } /* line 993, resources/main.scss */ .thumbnail-box { /* Hide pending images (they haven't been set up yet). */ /* * thumbnail-box[data-nearby] is set on thumbs that are close to being onscreen. * If they don't have data-nearby, tell the browser they're not visible. This * significantly improves performance when we have a lot of thumbs loaded, making * offscreen thumbs essentially free. * * Note that content-intrinsic-size is set programmatically. */ } /* line 995, resources/main.scss */ .thumbnail-box[data-pending] { visibility: hidden; } /* line 998, resources/main.scss */ .thumbnail-box .thumbnail-inner { position: relative; } /* line 1010, resources/main.scss */ .thumbnail-box:not([data-nearby]) .thumbnail-inner { content-visibility: hidden; } /* line 1014, resources/main.scss */ .thumbnail-box a.thumbnail-link { display: block; width: 100%; height: 100%; border-radius: 4px; overflow: hidden; position: relative; text-decoration: none; color: #fff; } /* line 1027, resources/main.scss */ .page-count-box { position: absolute; right: 2px; bottom: 2px; padding: 4px 8px; background-color: rgba(0, 0, 0, 0.6); border-radius: 6px; transition: opacity .5s; } /* line 1036, resources/main.scss */ .page-count-box .page-icon { width: 16px; height: 16px; display: inline-block; vertical-align: middle; } /* line 1043, resources/main.scss */ .page-count-box:hover .regular { display: none; } /* line 1046, resources/main.scss */ .page-count-box:not(:hover) .hover { display: none; } /* line 1050, resources/main.scss */ .page-count-box .page-count { vertical-align: middle; margin-left: -4px; } /* The similar illusts button on top of thumbnails. */ /* line 1059, resources/main.scss */ .screen-search-container .thumbnail-box .similar-illusts-button { display: block; width: 32px; height: 32px; margin-top: -2px; } /* line 1066, resources/main.scss */ .screen-search-container .thumbnail-box:not(:hover) .similar-illusts-button { visibility: hidden; } /* line 1070, resources/main.scss */ .screen-search-container .thumbnail-box .similar-illusts-button { color: #FF0 !important; /* override grey-icon hover color */ opacity: 0.5; /* Use a very subtle stroke when not hovered, so it's not completely invisible * on light backgrounds. */ stroke: rgba(0, 0, 0, 0.5); } /* line 1079, resources/main.scss */ .screen-search-container .thumbnail-box .similar-illusts-button:hover { opacity: 1; stroke: #000; } /* line 1084, resources/main.scss */ .screen-search-container .thumbnail-box .thumbnail-bottom-left { position: absolute; display: flex; left: 0px; bottom: 0px; } /* line 1090, resources/main.scss */ .screen-search-container .thumbnail-box .heart { pointer-events: none; width: 32px; height: 32px; } /* line 1095, resources/main.scss */ .screen-search-container .thumbnail-box .heart > svg { transition: opacity .5s; } /* line 1099, resources/main.scss */ .screen-search-container .thumbnail-box .ugoira-icon { pointer-events: none; width: 32px; height: 32px; right: 0px; bottom: 0px; color: #fff; position: absolute; transition: opacity .5s; } /* line 1111, resources/main.scss */ .screen-search-container .thumbnail-inner:hover .heart > svg { opacity: 0.5; } /* line 1114, resources/main.scss */ .screen-search-container .thumbnail-inner:hover .ugoira-icon { opacity: 0.5; } /* line 1121, resources/main.scss */ .thumbnail-box .thumb { object-fit: cover; /* Show the top-center of the thunbnail. This generally makes more sense * than cropping the center. */ object-position: 50% 0%; width: 100%; height: 100%; } /* line 1132, resources/main.scss */ .thumbnail-box[data-pending] .thumb { display: none; } /* line 1137, resources/main.scss */ .thumbnail-box .thumbnail-label { position: absolute; bottom: 3px; pointer-events: none; white-space: nowrap; color: var(--frame-fg-color); background-color: var(--frame-bg-color); left: 50%; position: absolute; transform: translate(-50%, 0); padding: 1px 8px; /* Max width fills the thumbnail the label is in, minus some space so we don't overlap bottom-left icons. */ max-width: calc(100% - 50px); overflow: hidden; border-radius: 2px; text-overflow: ellipsis; } /* line 1155, resources/main.scss */ .thumbnail-box .thumbnail-label > .label { /* Specify a line-height explicitly, so vertical centering is reasonably consistent for * both EN and JP text. */ line-height: 19px; } /* line 1163, resources/main.scss */ .thumbnail-box .thumb { transition: transform .5s; transform: scale(1, 1); } /* line 1173, resources/main.scss */ body:not(.disable-thumbnail-zooming) .thumbnail-box .thumbnail-inner:not(:hover) .thumb, body:not(.disable-thumbnail-zooming).pause-thumbnail-animation .thumbnail-box .thumb { transform: scale(1.25, 1.25); } /* line 1181, resources/main.scss */ .thumbnail-box.vertical-panning .thumb, .thumbnail-box.horizontal-panning .thumb { animation-duration: 4s; animation-timing-function: ease-in-out; animation-iteration-count: infinite; } /* line 1192, resources/main.scss */ .thumbnail-box .thumbnail-inner:not(:hover) .thumb, body.pause-thumbnail-animation .thumbnail-box .thumb { animation-play-state: paused; } /* line 1197, resources/main.scss */ body:not(.disable-thumbnail-panning) .thumbnail-box.horizontal-panning .thumb { animation-name: pan-thumbnail-horizontally; object-position: left top; /* The full animation is 4 seconds, and we want to start 20% in, at the halfway * point of the first left-right pan, where the pan is exactly in the center where * we are before any animation. This is different from vertical panning, since it * pans from the top, which is already where we start (top center). */ animation-delay: -.8s; } /* line 1208, resources/main.scss */ body:not(.disable-thumbnail-panning) .thumbnail-box.vertical-panning .thumb { animation-name: pan-thumbnail-vertically; } @keyframes pan-thumbnail-horizontally { /* This starts in the middle, pans left, pauses, pans right, pauses, returns to the middle, then pauses again. */ 0% { object-position: left top; } /* left */ 40% { object-position: right top; } /* pan right */ 50% { object-position: right top; } /* pause */ 90% { object-position: left top; } /* pan left */ 100% { object-position: left top; } /* pause */ } @keyframes pan-thumbnail-vertically { /* This starts at the top, pans down, pauses, pans back up, then pauses again. */ 0% { object-position: 50% 0%; } 40% { object-position: 50% 100%; } 50% { object-position: 50% 100%; } 90% { object-position: 50% 0%; } 100% { object-position: 50% 0%; } } /* line 1230, resources/main.scss */ .thumbnail-box.muted { /* Zoom muted images in a little, and zoom them out on hover, which is the opposite * of other images. This also helps hide the black bleed around the edge caused by * the blur. */ } /* line 1231, resources/main.scss */ .thumbnail-box.muted .muted-text { pointer-events: none; left: 0; top: 50%; width: 100%; height: 32px; position: absolute; color: #000; text-shadow: 0px 1px 1px #fff, 0px -1px 1px #fff, 1px 0px 1px #fff, -1px 0px 1px #fff; font-size: 22px; } /* line 1246, resources/main.scss */ .thumbnail-box.muted .thumb { filter: blur(10px); transform: scale(1.25, 1.25); } /* line 1251, resources/main.scss */ body:not(.disable-thumbnail-zooming) .thumbnail-box.muted .thumb:hover { transform: scale(1, 1); } /* line 1256, resources/main.scss */ .thumbnail-box:not(.muted) .muted-text { display: none; } /* line 1262, resources/main.scss */ .screen-search-container .following-tag { text-decoration: none; } /* line 1266, resources/main.scss */ .screen-search-container .right-side-button { display: inline-block; vertical-align: middle; cursor: pointer; user-select: none; } /* line 1272, resources/main.scss */ .screen-search-container .right-side-button > svg { vertical-align: middle; } /* line 1278, resources/main.scss */ .screen-search-container .edit-search-button { margin-left: -58px; /* overlap the input */ } /* line 1287, resources/main.scss */ .box-link-row { display: flex; flex-direction: row; align-items: center; gap: 0.5em; } /* line 1295, resources/main.scss */ .box-link-row > .box-link { padding-left: 0.25em; padding-right: 0.25em; } /* line 1302, resources/main.scss */ .box-button-row { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; } /* line 1308, resources/main.scss */ .box-button-row .box-link { margin: 0.25em .25em; padding: 0 .5em; } /* line 1317, resources/main.scss */ .box-button-row .box-link > * { padding: .25em 0; } /* line 1331, resources/main.scss */ .vertical-list > .box-link { padding: 0 .25em; } /* line 1333, resources/main.scss */ .vertical-list > .box-link { display: flex; flex-direction: row; align-items: center; margin-top: 0; margin-bottom: 0; } /* line 1344, resources/main.scss */ .box-link { display: inline-flex; cursor: pointer; text-decoration: none; margin: 0; align-content: center; align-items: center; height: 2em; color: var(--box-link-fg-color); background-color: var(--box-link-bg-color); user-select: none; white-space: nowrap; } /* line 1358, resources/main.scss */ .box-link.disabled { color: var(--box-link-disabled-color); cursor: auto; pointer-events: none; } /* line 1366, resources/main.scss */ .box-link:hover:not(.disabled) { background-color: var(--box-link-hover-color); } /* line 1370, resources/main.scss */ .box-link.selected { background-color: var(--box-link-selected-color); } /* line 1374, resources/main.scss */ .box-link.tag { /* Some tags are way too long, since translations don't put any sanity limit on length. * Cut these off so they don't break the layout. */ max-width: 100%; text-overflow: ellipsis; overflow: hidden; } /* line 1382, resources/main.scss */ .box-link .label { margin-left: .25em; } /* line 1386, resources/main.scss */ .box-link .icon { display: inline-block; width: 1em; position: relative; top: 0.125em; } /* line 1392, resources/main.scss */ .box-link .icon svg { width: auto; height: 1em; } /* line 1399, resources/main.scss */ .box-link.active { background-color: var(--box-link-selected-color); } /* line 1405, resources/main.scss */ a.box-link, span.box-link { padding-top: 0.5em; padding-bottom: 0.5em; } /* line 1411, resources/main.scss */ .search-box { white-space: nowrap; margin-bottom: 4px; position: relative; /* to position the search dropdown */ } /* The block around the input box and submit button. A history dropdown widget will * be placed in here. */ /* line 1419, resources/main.scss */ .tag-search-box { display: inline-block; position: relative; } /* line 1424, resources/main.scss */ input.search-users { font-size: 1.2em; padding: 6px 10px; vertical-align: middle; padding-right: 30px; /* extra space for the submit button */ } /* line 1430, resources/main.scss */ .user-search-box .search-submit-button { margin-left: -30px; /* overlap the input */ } /* line 1433, resources/main.scss */ input.search-tags { font-size: 1.2em; padding: 6px 10px; vertical-align: middle; } /* Search box in the search page: */ /* line 1440, resources/main.scss */ .tag-search-box input.search-tags { padding-right: 60px; /* extra space for the submit button */ } /* line 1444, resources/main.scss */ .search-submit-button { /* Work around HTML's stupid whitespace handling */ font-size: 0; display: inline-block; } /* Search box in the menu: */ /* line 1452, resources/main.scss */ .navigation-search-box .search-submit-button { vertical-align: middle; margin-left: -30px; /* overlap the search box */ } /* line 1456, resources/main.scss */ .navigation-search-box input.search-tags { padding-right: 30px; /* extra space for the submit button */ } /* line 1461, resources/main.scss */ .thumbnail-ui-box .avatar-container { float: right; position: relative; margin-left: 25px; } /* line 1467, resources/main.scss */ .image-for-suggestions { float: right; margin-left: 25px; } /* line 1471, resources/main.scss */ .image-for-suggestions > img { display: block; height: 150px; width: 150px; object-fit: cover; border-radius: 5px; /* matches the avatar display */ } /* line 1480, resources/main.scss */ .grey-icon { color: var(--button-color); cursor: pointer; /* If a grey-icon is directly inside a visible popup menu, eg. the navigation icon: */ } /* line 1486, resources/main.scss */ .grey-icon:hover, :hover > .grey-icon.parent-highlight { color: var(--button-highlight-color); } /* line 1493, resources/main.scss */ .popup-visible > .grey-icon { color: var(--button-highlight-color); } /* line 1499, resources/main.scss */ .mute-display .muted-image { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; filter: blur(20px); opacity: .75; } /* line 1510, resources/main.scss */ .mute-display .muted-text { position: absolute; width: 100%; top: 50%; left: 0; text-align: center; font-size: 30px; color: #000; text-shadow: 0px 1px 1px #fff, 0px -1px 1px #fff, 1px 0px 1px #fff, -1px 0px 1px #fff; } /* Tag lists are usually inline. Make the tag filter a vertical list. */ /* line 1523, resources/main.scss */ .member-tags-box .post-tag-list, .search-tags-box .related-tag-list { max-height: 300px; overflow-x: hidden; overflow-y: auto; white-space: nowrap; } /* line 1532, resources/main.scss */ .member-tags-box .post-tag-list .following-tag:hover:after, .search-tags-box .related-tag-list .tag:hover:after { left: auto; right: 0px; } /* These affect both the search edit and search history boxes. */ /* line 1539, resources/main.scss */ .input-dropdown { width: 500px; /* overridden by script */ max-width: 800px; margin: 1px; z-index: 1; user-select: none; /* Always show the vertical scrollbar. Otherwise, the resize handle falls under the buttons * when it's not shown. */ overflow-x: hidden; overflow-y: scroll; resize: horizontal; position: absolute; background-color: #fff; /* Styles specific to the search history version of the dropdown: */ /* Styles specific to the edit search version of the dropdown. */ } /* line 1554, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list { display: flex; flex-direction: column; white-space: normal; } /* line 1560, resources/main.scss */ .input-dropdown .input-dropdown-list > .entry { display: flex; flex-direction: row; color: #000; align-items: center; /* This 6px vertical padding should match the remove-history-entry padding. */ padding: 6px 0; } /* line 1569, resources/main.scss */ .input-dropdown .input-dropdown-list > .entry .search { color: #000; flex: 1; padding-left: 7px; height: 100%; } /* line 1576, resources/main.scss */ .input-dropdown .input-dropdown-list > .entry .search .word { display: inline-flex; align-items: center; height: 100%; padding: 0px 5px; } /* line 1582, resources/main.scss */ .input-dropdown .input-dropdown-list > .entry .search .word.or { font-size: 12px; padding: 0; color: #333; } /* line 1591, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list { /* Hide the button to remove history entries from non-history entries. */ } /* line 1592, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list > .entry .suggestion-icon { margin: 2px -2px 0 2px; } /* line 1595, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list > .entry:not(.autocomplete) .suggestion-icon { display: none; } /* line 1599, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list > .entry.selected { background-color: #ffa; } /* line 1603, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list > .entry:hover { background-color: #ddd; } /* line 1607, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list .remove-history-entry { height: 30px; width: 30px; /* Set an arbitrarily low negative margin. This makes it so the button extends into the * into the surrounding row's padding instead of pushing the whole row out. See * .input-dropdown-list > .entry padding. */ margin: -6px 0; display: inline-flex; align-items: center; justify-content: center; visibility: hidden; } /* line 1623, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list > .entry:not(.history) .remove-history-entry { display: none; } /* line 1627, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list > .entry:hover .remove-history-entry { visibility: visible; } /* line 1630, resources/main.scss */ .search-history > .input-dropdown > .input-dropdown-list .remove-history-entry:hover { color: #000; background-color: #c0c0c0; } /* line 1637, resources/main.scss */ .edit-search > .input-dropdown { padding: 4px 0; /* The edit search list is shown as a wrapped list, so enable wrapping and switch items from flex to inline-flex. */ } /* line 1641, resources/main.scss */ .edit-search > .input-dropdown > .input-dropdown-list { white-space: normal; max-width: 100%; } /* line 1645, resources/main.scss */ .edit-search > .input-dropdown > .input-dropdown-list > .entry { display: inline-flex; } /* line 1648, resources/main.scss */ .edit-search > .input-dropdown > .input-dropdown-list > .entry > A.search .tag.highlight { background-color: #eeee00; } /* line 1649, resources/main.scss */ .edit-search > .input-dropdown > .input-dropdown-list > .entry > A.search .tag:hover { background-color: #0099FF; } /* line 1650, resources/main.scss */ .edit-search > .input-dropdown > .input-dropdown-list > .entry > A.search .tag.highlight:hover { background-color: #00CCFF; } /* line 1657, resources/main.scss */ .manga-thumbnail-container { position: absolute; bottom: 0; left: 0; width: 100%; height: 240px; max-height: 30%; user-select: none; /* The .strip container is the overall strip. This is a flexbox that puts the nav * arrows on the outside, and the thumb strip stretching in the middle. The thumb * strip itself is also a flexbox, for the actual thumbs. */ } /* line 1667, resources/main.scss */ body.hide-ui .manga-thumbnail-container { display: none; } /* line 1675, resources/main.scss */ .manga-thumbnail-container > .strip { background-color: var(--ui-bg-color); height: 100%; display: flex; flex-direction: row; opacity: 0; transition: transform .15s, opacity .15s; transform: translate(0, 25px); } /* line 1686, resources/main.scss */ .manga-thumbnail-container > .strip > .manga-thumbnails { flex: 1; display: flex; flex-direction: row; overflow: hidden; justify-content: left; scroll-behavior: smooth; height: 100%; padding: 5px 0; } /* line 1699, resources/main.scss */ .manga-thumbnail-container.visible > .strip { opacity: 1; transform: translate(0, 0); } /* line 1705, resources/main.scss */ .manga-thumbnail-container .manga-thumbnail-box { cursor: pointer; height: 100%; margin: 0 5px; /* The first entry has the cursor inside it. Set these to relative, so the * cursor position is relative to it. */ position: relative; } /* line 1715, resources/main.scss */ .manga-thumbnail-container .manga-thumbnail-box img.manga-thumb { height: 100%; width: auto; border-radius: 3px; /* This will limit the width to 300px, cropping if needed. This prevents * very wide aspect ratio images from breaking the layout. Only a fixed * size will work here, percentage values won't work. */ max-width: 400px; object-fit: cover; } /* line 1730, resources/main.scss */ .manga-thumbnail-arrow { height: 100%; width: 30px; margin: 0 6px; } /* line 1736, resources/main.scss */ .manga-thumbnail-arrow > svg { fill: #888; } /* line 1740, resources/main.scss */ .manga-thumbnail-arrow:hover > svg { fill: #ff0; } /* line 1745, resources/main.scss */ body.light .manga-thumbnail-arrow { stroke: #aa0; } /* line 1750, resources/main.scss */ .manga-thumbnail-arrow > svg { display: block; height: 100%; width: 100%; padding: 4px; } /* line 1759, resources/main.scss */ .thumb-list-cursor { position: absolute; left: 0; bottom: -6px; width: 40px; height: 4px; background-color: var(--ui-fg-color); border-radius: 2px; } /* line 1770, resources/main.scss */ .widget:not(.visible-widget) { display: none; } /* The right click context menu for the image view: */ /* line 1776, resources/main.scss */ .popup-context-menu { color: #fff; position: fixed; top: 100px; left: 350px; text-align: left; padding: 10px; border-radius: 8px; display: flex; flex-direction: column; user-select: none; will-change: opacity, transform; transition: opacity ease 0.15s, transform ease 0.15s; /* Hide the normal tooltips. The context menu shows them differently. */ } /* line 1793, resources/main.scss */ .popup-context-menu:not(.visible-widget) { display: inherit; opacity: 0; pointer-events: none; transform: scale(0.85); } /* line 1801, resources/main.scss */ .popup-context-menu.visible-widget { opacity: 1; } /* line 1806, resources/main.scss */ .popup-context-menu > * { transform-origin: unset; } /* line 1811, resources/main.scss */ .popup-context-menu .popup:hover:after { display: none; } /* line 1815, resources/main.scss */ .popup-context-menu .tooltip-display { display: flex; align-items: stretch; padding: 10px 0 0 8px; pointer-events: none; } /* line 1822, resources/main.scss */ .popup-context-menu .tooltip-display .tooltip-display-text { background-color: var(--frame-bg-color); color: var(--frame-fg-color); padding: 2px 8px; border-radius: 4px; } /* line 1829, resources/main.scss */ .popup-context-menu .button-strip { display: flex; align-items: stretch; /* Remove the double horizontal padding: */ /* Remove the double vertical padding. Do this with a negative margin instead of zeroing * the padding, so the rounded black background stays the same size. */ /* Round the outer corners of each strip. */ /* This nudges the zoom strip to the left by the width of one button, to add the browser * back button to the left of other buttons. */ } /* line 1833, resources/main.scss */ .popup-context-menu .button-strip > .button-block { display: inline-block; background-color: var(--frame-bg-color); padding: 12px; } /* line 1840, resources/main.scss */ .popup-context-menu .button-strip > .button-block:not(:first-child) { padding-left: 0px; } /* line 1844, resources/main.scss */ .popup-context-menu .button-strip:not(:last-child) > .button-block { margin-bottom: -12px; } /* line 1847, resources/main.scss */ .popup-context-menu .button-strip > .button-block:first-child { border-radius: 5px 0 0 5px; } /* line 1848, resources/main.scss */ .popup-context-menu .button-strip > .button-block:last-child { border-radius: 0 5px 5px 0; } /* line 1850, resources/main.scss */ .popup-context-menu .button-strip .button { border-radius: 4px; padding: 6px; height: 100%; text-align: center; cursor: pointer; display: flex; flex-direction: column; justify-content: center; background-color: var(--toggle-button-bg-dim-color); color: var(--toggle-button-fg-dim-color); /* Grey out the buttons if this strip isn't enabled. */ /* We don't have a way to add classes to inlined SVGs yet, so for now just use nth-child. The first child is the + icon and the second child is -. */ /* Popup menu bookmarking */ } /* line 1863, resources/main.scss */ .popup-context-menu .button-strip .button:not(.enabled) { cursor: inherit; color: var(--toggle-button-fg-disabled-color); } /* line 1869, resources/main.scss */ .popup-context-menu .button-strip .button > * { min-width: 32px; } /* line 1872, resources/main.scss */ .popup-context-menu .button-strip .button > svg { width: 32px; height: 32px; } /* line 1877, resources/main.scss */ .popup-context-menu .button-strip .button.enabled:hover { color: var(--toggle-button-fg-color); } /* line 1881, resources/main.scss */ .popup-context-menu .button-strip .button.enabled.selected { background-color: var(--toggle-button-bg-color); color: var(--toggle-button-fg-color); } /* line 1888, resources/main.scss */ .popup-context-menu .button-strip .button.button-zoom:not(.selected) > :nth-child(1) { display: none; } /* line 1889, resources/main.scss */ .popup-context-menu .button-strip .button.button-zoom.selected > :nth-child(2) { display: none; } /* line 1892, resources/main.scss */ .popup-context-menu .button-strip .button .tag-dropdown-arrow { width: 0; height: 0; border-top: 10px solid #222; border-left: 10px solid transparent; border-right: 10px solid transparent; } /* line 1900, resources/main.scss */ body.light .popup-context-menu .button-strip .button .tag-dropdown-arrow { border-top-color: #ccc; } /* line 1907, resources/main.scss */ .popup-context-menu .button-strip > .button-block.shift-left { margin-left: -56px; } /* line 1912, resources/main.scss */ .popup-context-menu .context-menu-image-info { /* Bottom align within the row. */ align-self: flex-end; display: flex; flex-direction: column; align-items: center; background-color: var(--box-link-bg-color); padding-right: 8px; } /* line 1921, resources/main.scss */ .popup-context-menu .context-menu-image-info > * { background-color: var(--box-link-bg-color); color: var(--box-link-fg-color); padding: 2px 0 0px 0px; font-size: .8em; font-weight: bold; } /* line 1930, resources/main.scss */ .popup-context-menu .popup-bookmark-tag-dropdown { right: -100%; } /* line 1939, resources/main.scss */ .popup-more-options-container .button-send-image svg .arrow { transition: transform ease-in-out .15s; } /* line 1943, resources/main.scss */ .popup-more-options-container .button-send-image:not(.disabled):hover svg .arrow { transform: translate(2px, -2px); } /* line 1949, resources/main.scss */ .popup-bookmark-tag-dropdown, .popup-more-options-dropdown { background-color: var(--frame-bg-color); color: var(--frame-fg-color); position: absolute; padding: 8px; top: calc(100%); border-radius: 0px 0px 4px 4px; /* Put this on top of other elements, like the image-ui tag list. */ z-index: 1; /* In the context menu version, nudge the tag dropdown up slightly to cover * the rounded corners. */ /* Recent bookmark tags in the popup menu: */ } /* line 1963, resources/main.scss */ .popup-context-menu .popup-bookmark-tag-dropdown, .popup-context-menu .popup-more-options-dropdown { top: calc(100% - 4px); } /* line 1967, resources/main.scss */ .popup-bookmark-tag-dropdown > .tag-list, .popup-more-options-dropdown > .tag-list { display: flex; flex-direction: column; min-width: 200px; overflow-x: hidden; overflow-y: auto; } /* line 1975, resources/main.scss */ .popup-bookmark-tag-dropdown > .tag-right-button-strip, .popup-more-options-dropdown > .tag-right-button-strip { position: absolute; top: 0; left: 100%; background-color: var(--frame-bg-color); color: var(--frame-fg-color); display: flex; flex-direction: column; align-items: stretch; } /* line 1985, resources/main.scss */ .popup-bookmark-tag-dropdown > .tag-right-button-strip .tag-button, .popup-more-options-dropdown > .tag-right-button-strip .tag-button { cursor: pointer; } /* line 1991, resources/main.scss */ .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry, .popup-more-options-dropdown .popup-bookmark-tag-entry { display: flex; flex-direction: row; align-items: center; padding: 4px 0px; display: flex; cursor: pointer; } /* line 1998, resources/main.scss */ .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry > .tag-name, .popup-more-options-dropdown .popup-bookmark-tag-entry > .tag-name { flex: 1; } /* line 2001, resources/main.scss */ .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry.active, .popup-more-options-dropdown .popup-bookmark-tag-entry.active { background-color: #008; } /* line 2004, resources/main.scss */ body.light .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry.active, body.light .popup-more-options-dropdown .popup-bookmark-tag-entry.active { background-color: #00c; color: #fff; } /* line 2008, resources/main.scss */ .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry.active:hover, .popup-more-options-dropdown .popup-bookmark-tag-entry.active:hover { background-color: #00a; } /* line 2011, resources/main.scss */ body.light .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry.active:hover, body.light .popup-more-options-dropdown .popup-bookmark-tag-entry.active:hover { background-color: #00a; } /* line 2014, resources/main.scss */ .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry:not(.active):hover, .popup-more-options-dropdown .popup-bookmark-tag-entry:not(.active):hover { background-color: #222; } /* line 2017, resources/main.scss */ body.light .popup-bookmark-tag-dropdown .popup-bookmark-tag-entry:not(.active):hover, body.light .popup-more-options-dropdown .popup-bookmark-tag-entry:not(.active):hover { background-color: #ccc; } /* line 2023, resources/main.scss */ .button.button-bookmark .count, .button.button-like .count { color: var(--minor-text-fg-color); text-shadow: 0px 1px 1px var(--minor-text-shadow-color), 0px -1px 1px var(--minor-text-shadow-color), 1px 0px 1px var(--minor-text-shadow-color), -1px 0px 1px var(--minor-text-shadow-color); font-size: .7em; font-weight: bold; position: absolute; top: calc(100% - 14px); left: 0; width: 100%; text-align: center; } /* Nudge the public heart icon up a bit to make room for the bookmark count. * Only do this on the popup menu, not image-ui. */ /* line 2044, resources/main.scss */ .popup-context-menu .button.button-bookmark.public > svg { margin-top: -10px; } /* line 2048, resources/main.scss */ .popup-context-menu .button.button-like > svg { margin-top: -2px; } /* Bookmark buttons. These appear in image_ui and the popup menu. */ /* line 2054, resources/main.scss */ .button.button-bookmark.will-delete.enabled:hover svg.heart-image .delete { display: inline; } /* Hide the "delete" stroke over the heart icon unless clicking the button will * remove the bookmark. */ /* line 2060, resources/main.scss */ svg.heart-image .delete { display: none; } /* These are !important to override the default white coloring in the context * menu. */ /* line 2066, resources/main.scss */ .button-bookmark { color: #400 !important; } /* line 2068, resources/main.scss */ .button-bookmark.enabled { color: #800 !important; stroke: none; } /* line 2073, resources/main.scss */ .button-bookmark.bookmarked, .button-bookmark.enabled:hover { color: #f00 !important; stroke: none; } /* Add a stroke around the heart on thumbnails for visibility. Don't * change the black lock. */ /* line 2082, resources/main.scss */ .screen-search-container .thumbnails .button-bookmark svg > .heart { stroke: #000; stroke-width: .5px; } /* line 2087, resources/main.scss */ .button.button-like { /* This is a pain due to transition bugs in Firefox. It doesn't like having * transition: transform on both an SVG and on individual paths inside the * SVG and clips the image incorrectly during the animation. Work around this * by only placing transitions on the paths. */ } /* line 2092, resources/main.scss */ .button.button-like > svg { color: var(--like-button-color); } /* line 2096, resources/main.scss */ .button.button-like.liked > svg { color: var(--like-button-liked-color); } /* line 2099, resources/main.scss */ .button.button-like.enabled:hover > svg { color: var(--like-button-hover-color); } /* line 2105, resources/main.scss */ .button.button-browser-back .arrow { transition: transform ease-in-out .15s; transform: translate(-2px, 0px); } /* line 2109, resources/main.scss */ .button.button-browser-back:hover .arrow { transform: translate(1px, 0px); } /* line 2114, resources/main.scss */ .button.button-like > svg > * { transition: transform ease-in-out .15s; transform: translate(0, 0px); } /* line 2118, resources/main.scss */ .button.button-like > svg > .mouth { transform: scale(1, 0.75); } /* line 2122, resources/main.scss */ .button.button-like.liked > svg > * { transform: translate(0, -3px); } /* line 2125, resources/main.scss */ .button.button-like.liked > svg > .mouth { transform: scale(1, 1.1) translate(0, -3px); } /* line 2128, resources/main.scss */ .button.button-like.enabled:hover > svg > * { transform: translate(0, -2px); } /* line 2131, resources/main.scss */ .button.button-like.enabled:hover > svg > .mouth { transform: scale(1, 0.9) translate(0, -3px); } /* line 2134, resources/main.scss */ .button-bookmark.public svg.heart-image .lock { display: none; } /* line 2137, resources/main.scss */ .button-bookmark svg.heart-image .lock { stroke: #888; } /* line 2141, resources/main.scss */ .dialog { position: absolute; z-index: 1000; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.75); display: flex; align-items: center; justify-content: center; } /* line 2153, resources/main.scss */ .dialog .content { font-size: 18px; max-width: 800px; background-color: var(--ui-bg-color); color: var(--ui-fg-color); border-radius: 5px; position: relative; } /* line 2161, resources/main.scss */ .dialog .content > .scroll { width: 100%; height: 100%; overflow-y: auto; padding: 1em; } /* line 2169, resources/main.scss */ .dialog .header { font-size: 40px; margin-bottom: 20px; } /* line 2175, resources/main.scss */ .whats-new-box .content { width: 80%; height: 80%; } /* line 2179, resources/main.scss */ .whats-new-box .content .rev { display: inline-block; color: var(--box-link-fg-color); background-color: var(--box-link-bg-color); padding: 5px 10px; } /* line 2185, resources/main.scss */ .whats-new-box .content .text { margin: 1em 0; padding: 0 20px; /* inset horizontally a bit */ } /* line 2191, resources/main.scss */ .close-button { position: absolute; top: 5px; right: -40px; color: var(--button-color); background-color: var(--ui-bg-color); padding: 4px; border-radius: 5px; cursor: pointer; } /* line 2200, resources/main.scss */ .close-button:hover { color: var(--button-highlight-color); } /* line 2203, resources/main.scss */ .close-button > svg { display: block; } /* line 2209, resources/main.scss */ .screen-illust-container .page-change-indicator { position: absolute; height: 100%; display: flex; align-items: center; pointer-events: none; /* Hide the | portion of >| when showing last page rather than end of results. */ } /* line 2216, resources/main.scss */ .screen-illust-container .page-change-indicator[data-side="left"] { margin-left: 20px; left: 0; } /* line 2221, resources/main.scss */ .screen-illust-container .page-change-indicator[data-side="right"] { margin-right: 20px; right: 0; } /* line 2226, resources/main.scss */ .screen-illust-container .page-change-indicator[data-side="right"] svg { transform-origin: center center; transform: scale(-1, 1); } /* line 2232, resources/main.scss */ .screen-illust-container .page-change-indicator[data-icon="last-page"] svg .bar { display: none; } /* line 2235, resources/main.scss */ .screen-illust-container .page-change-indicator svg { opacity: 0; } /* line 2238, resources/main.scss */ .screen-illust-container .page-change-indicator.flash svg { animation: flash-page-change-opacity 400ms ease-out 1 forwards; } /* line 2242, resources/main.scss */ .screen-illust-container .page-change-indicator.flash svg .animated { animation: flash-page-change-part 300ms ease-out 1 forwards; } @keyframes flash-page-change-opacity { 0% { opacity: 1; } 40% { opacity: 1; } 80% { opacity: 0; } } @keyframes flash-page-change-part { 0% { transform: translate(0, 0px); } 20% { transform: translate(-4px, 0px); } 100% { transform: translate(0, 0px); } } /* line 2262, resources/main.scss */ .link-tab-popup .button { display: inline-block; cursor: pointer; background-color: #000; padding: .5em 1em; margin: .5em; border-radius: 5px; } /* line 2271, resources/main.scss */ .link-tab-popup .content { width: 400px; padding: 1em; } /* line 2276, resources/main.scss */ .link-tab-popup .buttons { display: flex; } /* line 2280, resources/main.scss */ .link-tab-popup .tutorial-monitor { width: 290px; height: 125px; margin-bottom: -20px; } /* line 2288, resources/main.scss */ .link-tab-popup .tutorial-monitor .rotating-monitor { transform-origin: 75px 30px; animation: rotate-monitor 4500ms linear infinite; } @keyframes rotate-monitor { 0% { transform: rotate(0deg); } 10% { transform: rotate(90deg); } 50% { transform: rotate(90deg); } 60% { transform: rotate(0deg); } } /* line 2305, resources/main.scss */ .send-image-popup .content { padding: 1em; } /* line 2312, resources/main.scss */ .link-this-tab-popup > .box, .send-image-here-popup > .box { border: 1px solid black; background-color: #000; color: #fff; padding: 1em; } /* line 2319, resources/main.scss */ .link-this-tab-popup .button, .send-image-here-popup .button { cursor: pointer; padding: 1em; } /* line 2325, resources/main.scss */ .tag-entry-popup { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); } /* line 2334, resources/main.scss */ .tag-entry-popup > .strip { display: flex; flex-direction: column; align-items: center; height: 100%; justify-content: center; } /* line 2340, resources/main.scss */ .tag-entry-popup > .strip > .box { background-color: #222; padding: 10px; color: #eee; position: relative; } /* line 2346, resources/main.scss */ body.light .tag-entry-popup > .strip > .box { background-color: #ddd; color: #222; } /* line 2353, resources/main.scss */ .tag-entry-popup .close-button { position: absolute; top: 0px; right: 0px; padding: 8px; cursor: pointer; } /* line 2361, resources/main.scss */ .tag-entry-popup .tag-input-box { position: relative; display: flex; align-items: center; } /* line 2366, resources/main.scss */ .tag-entry-popup .tag-input-box > .add-tag-input { flex: 1; padding: 4px; } /* line 2370, resources/main.scss */ .tag-entry-popup .tag-input-box > .submit-button { cursor: pointer; display: inline-block; width: 20px; text-align: center; margin-left: 6px; border: 1px solid white; } /* line 2377, resources/main.scss */ body.light .tag-entry-popup .tag-input-box > .submit-button { border-color: #444; } /* line 2380, resources/main.scss */ .tag-entry-popup .tag-input-box > .submit-button:hover { background-color: #444; } /* line 2382, resources/main.scss */ body.light .tag-entry-popup .tag-input-box > .submit-button:hover { background-color: #aaa; } /* line 2387, resources/main.scss */ .years-ago { padding: .25em; margin: .25em; white-space: nowrap; /* These links are mostly the same as box-link, but since the * menu background is the same as the box-link background color, * shift it a little to make it clear these are buttons. */ } /* line 2394, resources/main.scss */ .years-ago > a { padding: 4px 10px; background-color: #444; } /* line 2397, resources/main.scss */ body.light .years-ago > a { background-color: #ccc; } /*# sourceMappingURL=https://raw.githubusercontent.com/ppixiv/ppixiv/r119/output/main.scss.map */`; ppixiv.resources["resources/multi-monitor.svg"] = ` `; ppixiv.resources["resources/noise-light.png"] = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAD1BMVEXo6Ojn5+fo6Ojn5+fn5+cbG+42AAAACXBIWXMAAAsTAAALEwEAmpwYAAAF62lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAxOC0wNi0yNlQyMzowMjo0My0wNTowMCIgeG1wOk1vZGlmeURhdGU9IjIwMTgtMDctMDFUMTc6MjI6MzctMDU6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMTgtMDctMDFUMTc6MjI6MzctMDU6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIyIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OWM1ZTI1ZTktNmM0Ny1lMTRkLWI1NmYtMWM3MWRhOTk3NzAxIiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ODcxMzVhMGQtMTYwMy1hODRhLTliZWMtNGJhMDllZDE1NGQ2IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MTEzYjRiYTgtMmYzNC0zZTQ2LTgyZmUtNTM2ZDNlZDgzYTlmIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxMTNiNGJhOC0yZjM0LTNlNDYtODJmZS01MzZkM2VkODNhOWYiIHN0RXZ0OndoZW49IjIwMTgtMDYtMjZUMjM6MDI6NDMtMDU6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjljNWUyNWU5LTZjNDctZTE0ZC1iNTZmLTFjNzFkYTk5NzcwMSIgc3RFdnQ6d2hlbj0iMjAxOC0wNy0wMVQxNzoyMjozNy0wNTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5BpB4MAAAWVUlEQVR4nKWb25osuXGrfyD4/k9cBHwRzDXy/rw9GvmuR+pVncWMA04cTq2C5I5wXU5HHRDgnmL11BVjMK4BMHY1cFAFTCU4OQVOjEd2ZVdIs3/JPZURwhpF2KoYUDUXMDkXJGlQVHxVixbXtqIpo5rpJArIBQtfh4FiEairACgUaaIgcHGYwQRcpVJ8B1oQnOJQdQD1BDuI1CkuwZf4GnRUVVKLW3D3b8oR/U4TI4JVFeFqptSFY4AWWWIa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`; ppixiv.resources["resources/noise.png"] = `data:image/png;base64,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`; ppixiv.resources["resources/page-icon-hover.png"] = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGu2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAxOC0wNi0zMFQwMjowMToxNy0wNTowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMC0wMS0xMlQxODo1NDowNi0wNjowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDEtMTJUMTg6NTQ6MDYtMDY6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YTk5ZGEzMWUtNTM5Zi03OTQ3LWI5MzMtNzRiYzliZDMyYjRmIiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6MjE2NDcxMGYtOTM5My1hZjRmLTg3ZWUtY2NmY2YxNGIzMjYzIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ZTAzMzRhNzEtMmQ2Mi1lNDRjLWFiMjUtZGJjZTNlYTcwNTYwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9InNSR0IgSUVDNjE5NjYtMi4xIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDplMDMzNGE3MS0yZDYyLWU0NGMtYWIyNS1kYmNlM2VhNzA1NjAiIHN0RXZ0OndoZW49IjIwMTgtMDYtMzBUMDI6MDE6MTctMDU6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjYxNjM4NWIxLTA4YjUtZDI0YS1iNDMyLTcwM2IwZjQxYzYxOSIgc3RFdnQ6d2hlbj0iMjAxOC0wNi0zMFQwMjowMToxNy0wNTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6YTk5ZGEzMWUtNTM5Zi03OTQ3LWI5MzMtNzRiYzliZDMyYjRmIiBzdEV2dDp3aGVuPSIyMDIwLTAxLTEyVDE4OjU0OjA2LTA2OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+iRnHuAAAAEFJREFUOI1j/P//PwMlgIki3QwMDCxIbEJOYaSJC0g14D8Dmkvp7oLhaAByOsAaz6QYAAMkpW2qegEGSPLKwMcCANSMByRCC4aMAAAAAElFTkSuQmCC`; ppixiv.resources["resources/page-icon.png"] = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFwmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAxOC0wNi0zMFQwMjowMToxNy0wNTowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOC0wNi0zMFQwMjowMToxNy0wNTowMCIgeG1wOk1vZGlmeURhdGU9IjIwMTgtMDYtMzBUMDI6MDE6MTctMDU6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjE2Mzg1YjEtMDhiNS1kMjRhLWI0MzItNzAzYjBmNDFjNjE5IiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6YmNlMzU0ZTgtMDE3Zi1iMjRkLTg4MTYtOGZkZTZlYTgyZDg5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ZTAzMzRhNzEtMmQ2Mi1lNDRjLWFiMjUtZGJjZTNlYTcwNTYwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyI+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ZTAzMzRhNzEtMmQ2Mi1lNDRjLWFiMjUtZGJjZTNlYTcwNTYwIiBzdEV2dDp3aGVuPSIyMDE4LTA2LTMwVDAyOjAxOjE3LTA1OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTYzODViMS0wOGI1LWQyNGEtYjQzMi03MDNiMGY0MWM2MTkiIHN0RXZ0OndoZW49IjIwMTgtMDYtMzBUMDI6MDE6MTctMDU6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+1Ie7qQAAADpJREFUOI1j/P//PwMlgIki3dQwgAWNT8g/jNRwAYolAx8GowZgpgOMeCbVAAYGwomJoAEkuWLgAxEAc7EGJRNwU4UAAAAASUVORK5CYII=`; ppixiv.resources["resources/pixiv-icon.svg"] = ` `; ppixiv.resources["resources/play-button.svg"] = ` `; ppixiv.resources["resources/refresh-icon.svg"] = ` `; ppixiv.resources["resources/regular-pixiv-icon.png"] = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAADACAMAAABlApw1AAAAG1BMVEX///8Alvqe1/1SuPwYoPvn9v/F5/40rPt2x/37JN9BAAAEBElEQVR42u3c23YsERAG4EJR3v+J92SSycqe0d2UYkh+F7nKEl+jHAJymycCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBVACwhe59SjJGIbj9TSj4H4fUBfCt5ouOUfJBlAZx9pJqUsqwHCJWF/0rRh4UA3Fj6h0GWAHBIpE0pvB0gmm//sxryOwGczz/+PX5+htKTXwrvArA/ad63oP+zhctZdFUTqK/tHJZdjvv6ASLxbIAkZYCXHO26AtkWP+W671iOWppKIMO2HzN3Nj9FTyCz4jfH82Id5hmAUhNOmhE1FwR+OKD04ZJyQsCpuyOQwVfrGUlzr6AREKJZAH/k2JkhdXde6pwTS+wSUN+fMgAUBUMAR9Oe7lVJQeDtAXI4D+tfVknHeEAdvdcMUOrJYgvIJ5N5A0Ah/2gJ4NM1iwXAJW0jovZOlvwAAEdlI6LmBprdCIC6EVFrzsGNAWgb0SXg/9JGcaMAr7E0sgEgvZZ/EKAwUOZ+QCp9kkEAVlUBNYTPR36DALoqoPbyDwOIJhBRffnFDQYUAlHoADwPv+KGA4JiXk3149d4gHudp3BHE/JHE/RxAEU3prrpSXRTALm9DVFddjIHwO1tiKqigndzAIo4RDWB+WlEHAjwzatjqsnPu1mA9kB6MReKpUwGAgrL+z5AKGUyEOCaV/dU1Sin9QEXW3vxFeBzMJBpgOZ12eWKLM+tgeYwRDXfZF4nbh+LqSIwPG8Wbwa4rObBgLgXIPw+AAEAwJ/qxL8QsNk4MGAqMReQdgeYT6cnA9h8QTMZEKyXlLMB3npRPxuQjLdVZgOYbDe2pgOC8dbidECy3dydDlC0oLUAWfF/yqUAmoNPKwFUp4ZWAii68FIA3bGtdQCsO7y4DsDrzs0tAxDlOfBlAFF3XGgZgNceJlwEkNUXCdYAFCJo5I0AhQ5sfXJ3KKB0Kt787PRAQFf5FwCEvptAbwf03mR6M6B4rDy5bQDFWwltN8kMAOor2eVLIY13ugwASsLBVeTWrEwAH/UeTIofm68EWgHujyxUX/86uknt2wtjB/h6s4MrSh8Nr6XbAu7FSCcPqMjJwx9edaXRHvBgeJ9zCCLCtyQS8sWDK8oLsaMArU9LqAcTA0B8Y/FNANz5skff2yQWgHvnVD6u0v06jBHANbwsZPcwjC3gKkr2DHzTAPeaCD7Fy8Jnq0eq7AFfio8HwkoX8JNd2UcCvtuUhNsI9pHCLVm/cDYBMD4BAAAAAAAAAAAAAPC3AM+bypl3AnDpkTkv2wBytNwWnA8Ix/sLewBONn9kC8DJ+668BYD9UQq7RKHlEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQnP4BoAuIrpag2iEAAAAASUVORK5CYII=`; ppixiv.resources["resources/related-illusts.svg"] = ` `; ppixiv.resources["resources/search-icon.svg"] = ``; ppixiv.resources["resources/search-result-icon.svg"] = ` `; ppixiv.resources["resources/send-message.svg"] = ` `; ppixiv.resources["resources/send-to-tab.svg"] = ` `; ppixiv.resources["resources/settings-icon.svg"] = ` `; ppixiv.resources["resources/shopping-cart.svg"] = ` `; ppixiv.resources["resources/tag-icon.svg"] = ` `; ppixiv.resources["resources/thumbnails-icon.svg"] = ` `; ppixiv.resources["resources/whats-new.svg"] = ` `; ppixiv.resources["resources/zoom-actual.svg"] = ` `; ppixiv.resources["resources/zoom-full.svg"] = ` `; ppixiv.resources["resources/zoom-minus.svg"] = ` `; ppixiv.resources["resources/zoom-plus.svg"] = ` `; ppixiv.resources["output/setup.js"] = { "source_files": [ "src/actions.js", "src/muting.js", "src/crc32.js", "src/helpers.js", "src/settings.js", "src/fix_chrome_clicks.js", "src/widgets.js", "src/menu_option.js", "src/main_context_menu.js", "src/create_zip.js", "src/data_sources.js", "src/encode_mkv.js", "src/hide_mouse_cursor_on_idle.js", "src/image_data.js", "src/on_click_viewer.js", "src/polyfills.js", "src/progress_bar.js", "src/seek_bar.js", "src/struct.js", "src/ugoira_downloader_mjpeg.js", "src/viewer.js", "src/viewer_images.js", "src/viewer_muted.js", "src/viewer_ugoira.js", "src/zip_image_player.js", "src/screen.js", "src/screen_illust.js", "src/screen_search.js", "src/screen_manga.js", "src/image_ui.js", "src/tag_search_dropdown_widget.js", "src/recently_seen_illusts.js", "src/tag_translations.js", "src/thumbnail_data.js", "src/manga_thumbnail_widget.js", "src/page_manager.js", "src/remove_link_interstitial.js", "src/image_preloading.js", "src/whats_new.js", "src/send_image.js", "src/main.js" ] } ; ppixiv.resources["src/actions.js"] = `"use strict"; // Global actions. ppixiv.actions = class { // Set a bookmark. Any existing bookmark will be overwritten. static async _bookmark_add_internal(illust_id, options) { let illust_info = await thumbnail_data.singleton().get_or_load_illust_data(illust_id); if(options == null) options = {}; console.log("Add bookmark:", options); // If auto-like is enabled, like an image when we bookmark it. if(!options.disable_auto_like) { console.log("Automatically liking image with bookmark"); actions.like_image(illust_id, true /* quiet */); } // Remember whether this is a new bookmark or an edit. var was_bookmarked = illust_info.bookmarkData != null; var request = { "illust_id": illust_id, "tags": options.tags || [], "restrict": options.private? 1:0, } var result = await helpers.post_request("/ajax/illusts/bookmarks/add", request); // If this is a new bookmark, last_bookmark_id is the new bookmark ID. // If we're editing an existing bookmark, last_bookmark_id is null and the // bookmark ID doesn't change. var new_bookmark_id = result.body.last_bookmark_id; if(new_bookmark_id == null) new_bookmark_id = illust_info.bookmarkData? illust_info.bookmarkData.id:null; if(new_bookmark_id == null) throw "Didn't get a bookmark ID"; // Store the ID of the new bookmark, so the unbookmark button works. thumbnail_data.singleton().update_illust_data(illust_id, { bookmarkData: { id: new_bookmark_id, private: !!request.restrict, }, }); // Even if we weren't given tags, we still know that they're unset, so set tags so // we won't need to request bookmark details later. image_data.singleton().update_cached_bookmark_image_tags(illust_id, request.tags); console.log("Updated bookmark data:", illust_id, new_bookmark_id, request.restrict, request.tags); if(!was_bookmarked) { // If we have full illust data loaded, increase its bookmark count locally. let full_illust_info = image_data.singleton().get_image_info_sync(illust_id); if(full_illust_info) full_illust_info.bookmarkCount++; } message_widget.singleton.show( was_bookmarked? "Bookmark edited": options.private? "Bookmarked privately":"Bookmarked"); image_data.singleton().call_illust_modified_callbacks(illust_id); } // Create or edit a bookmark. // // Create or edit a bookmark. options can contain any of the fields tags or private. // Fields that aren't specified will be left unchanged on an existing bookmark. // // This is a headache. Pixiv only has APIs to create a new bookmark (overwriting all // existing data), except for public/private which can be changed in-place, and we need // to do an extra request to retrieve the tag list if we need it. We try to avoid // making the extra bookmark details request if possible. static async bookmark_add(illust_id, options) { if(options == null) options = {}; let illust_info = await thumbnail_data.singleton().get_or_load_illust_data(illust_id); console.log("Add bookmark for", illust_id, "options:", options); // This is a mess, since Pixiv's APIs are all over the place. // // If the image isn't already bookmarked, just use bookmark_add. if(illust_info.bookmarkData == null) { console.log("Initial bookmark"); if(options.tags != null) helpers.update_recent_bookmark_tags(options.tags); return await actions._bookmark_add_internal(illust_id, options); } // Special case: If we're not setting anything, then we just want this image to // be bookmarked. Since it is, just stop. if(options.tags == null && options.private == null) { console.log("Already bookmarked"); return; } // Special case: If all we're changing is the private flag, use bookmark_set_private // so we don't fetch bookmark details. if(options.tags == null && options.private != null) { // If the image is already bookmarked, use bookmark_set_private to edit the // existing bookmark. This won't auto-like. console.log("Only editing private field", options.private); return await actions.bookmark_set_private(illust_id, options.private); } // If we're modifying tags, we need bookmark details loaded, so we can preserve // the current privacy status. This will insert the info into illust_info.bookmarkData. let bookmark_tags = await image_data.singleton().load_bookmark_details(illust_id); var bookmark_params = { // Don't auto-like if we're editing an existing bookmark. disable_auto_like: true, }; if("private" in options) bookmark_params.private = options.private; else bookmark_params.private = illust_info.bookmarkData.private; if("tags" in options) bookmark_params.tags = options.tags; else bookmark_params.tags = bookmark_tags; // Only update recent tags if we're modifying tags. if(options.tags != null) { // Only add new tags to recent tags. If a bookmark has tags "a b" and is being // changed to "a b c", only add "c" to recently-used tags, so we don't bump tags // that aren't changing. for(var tag of options.tags) { var is_new_tag = bookmark_tags.indexOf(tag) == -1; if(is_new_tag) helpers.update_recent_bookmark_tags([tag]); } } return await actions._bookmark_add_internal(illust_id, bookmark_params); } static async bookmark_remove(illust_id) { let illust_info = await thumbnail_data.singleton().get_or_load_illust_data(illust_id); if(illust_info.bookmarkData == null) { console.log("Not bookmarked"); return; } var bookmark_id = illust_info.bookmarkData.id; console.log("Remove bookmark", bookmark_id); var result = await helpers.post_request("/ajax/illusts/bookmarks/remove", { bookmarkIds: [bookmark_id], }); console.log("Removing bookmark finished"); thumbnail_data.singleton().update_illust_data(illust_id, { bookmarkData: null }); // If we have full image data loaded, update the like count locally. let illust_data = image_data.singleton().get_image_info_sync(illust_id); if(illust_data) { illust_data.bookmarkCount--; image_data.singleton().call_illust_modified_callbacks(illust_id); } image_data.singleton().update_cached_bookmark_image_tags(illust_id, null); message_widget.singleton.show("Bookmark removed"); image_data.singleton().call_illust_modified_callbacks(illust_id); } // Change an existing bookmark to public or private. static async bookmark_set_private(illust_id, private_bookmark) { let illust_info = await thumbnail_data.singleton().get_or_load_illust_data(illust_id); if(!illust_info.bookmarkData) { console.log(\`Illust \${illust_id} wasn't bookmarked\`); return; } let bookmark_id = illust_info.bookmarkData.id; let result = await helpers.post_request("/ajax/illusts/bookmarks/edit_restrict", { bookmarkIds: [bookmark_id], bookmarkRestrict: private_bookmark? "private":"public", }); // Update bookmark info. thumbnail_data.singleton().update_illust_data(illust_id, { bookmarkData: { id: bookmark_id, private: private_bookmark, }, }); message_widget.singleton.show(private_bookmark? "Bookmarked privately":"Bookmarked"); image_data.singleton().call_illust_modified_callbacks(illust_id); } // Show a prompt to enter tags, so the user can add tags that aren't already in the // list. Add the bookmarks to recents, and bookmark the image with the entered tags. static async add_new_tag(illust_id) { let illust_data = await image_data.singleton().get_image_info(illust_id); console.log("Show tag prompt"); // Hide the popup when we show the prompt. this.hide_temporarily = true; var prompt = new text_prompt({}); try { var tags = await prompt.result; } catch(e) { // The user cancelled the prompt. return; } // Split the new tags. tags = tags.split(" "); tags = tags.filter((value) => { return value != ""; }); console.log("New tags:", tags); // This should already be loaded, since the only way to open this prompt is // in the tag dropdown. let bookmark_tags = await image_data.singleton().load_bookmark_details(illust_data.illustId); // Add each tag the user entered to the tag list to update it. let active_tags = [...bookmark_tags]; for(let tag of tags) { if(active_tags.indexOf(tag) != -1) continue; // Add this tag to recents. bookmark_add will add recents too, but this makes sure // that we add all explicitly entered tags to recents, since bookmark_add will only // add tags that are new to the image. helpers.update_recent_bookmark_tags([tag]); active_tags.push(tag); } console.log("All tags:", active_tags); // Edit the bookmark. await actions.bookmark_add(illust_id, { tags: active_tags, }); } // If quiet is true, don't print any messages. static async like_image(illust_id, quiet) { console.log("Clicked like on", illust_id); if(image_data.singleton().get_liked_recently(illust_id)) { if(!quiet) message_widget.singleton.show("Already liked this image"); return; } var result = await helpers.post_request("/ajax/illusts/like", { "illust_id": illust_id, }); // If is_liked is true, we already liked the image, so this had no effect. let was_already_liked = result.body.is_liked; // Remember that we liked this image recently. image_data.singleton().add_liked_recently(illust_id); // If we have illust data, increase the like count locally. Don't load it // if it's not loaded already. let illust_data = image_data.singleton().get_image_info_sync(illust_id); if(!was_already_liked && illust_data) { illust_data.likeCount++; image_data.singleton().call_illust_modified_callbacks(illust_id); } if(!quiet) { if(was_already_liked) message_widget.singleton.show("Already liked this image"); else message_widget.singleton.show("Illustration liked"); } } static async follow(user_id, follow_privately, tags) { var result = await helpers.rpc_post_request("/bookmark_add.php", { mode: "add", type: "user", user_id: user_id, tag: tags, restrict: follow_privately? 1:0, format: "json", }); // This doesn't return any data. Record that we're following and refresh the UI. let user_data = await image_data.singleton().get_user_info(user_id); user_data.isFollowed = true; image_data.singleton().call_user_modified_callbacks(user_data.userId); var message = "Followed " + user_data.name; if(follow_privately) message += " privately"; message_widget.singleton.show(message); } static async unfollow(user_id) { var result = await helpers.rpc_post_request("/rpc_group_setting.php", { mode: "del", type: "bookuser", id: user_id, }); // Record that we're no longer following and refresh the UI. let user_data = await image_data.singleton().get_user_info(user_id); user_data.isFollowed = false; image_data.singleton().call_user_modified_callbacks(user_data.userId); message_widget.singleton.show("Unfollowed " + user_data.name); } // Image downloading // // Download illust_data. static async download_illust(illust_id, progress_bar_controller, download_type, manga_page) { let illust_data = await image_data.singleton().get_image_info(illust_id, { load_user_info: true }); let user_info = await image_data.singleton().get_user_info(illust_data.userId); console.log("Download", illust_id, "with type", download_type); if(download_type == "MKV") { new ugoira_downloader_mjpeg(illust_data, progress_bar_controller); return; } if(download_type != "image" && download_type != "ZIP") { console.error("Unknown download type " + download_type); return; } // If we're in ZIP mode, download all images in the post. // // Pixiv's host for images changed from i.pximg.net to i-cf.pximg.net. This will fail currently for that // host, since it's not in @connect, and adding that will prompt everyone for permission. Work around that // by replacing i-cf.pixiv.net with i.pixiv.net, since that host still works fine. This only affects downloads. var images = []; for(var page of illust_data.mangaPages) { let url = page.urls.original; url = url.replace(/:\\/\\/i-cf.pximg.net/, "://i.pximg.net"); images.push(url); } // If we're in image mode for a manga post, only download the requested page. if(download_type == "image") images = [images[manga_page]]; let results = await helpers.download_urls(images); // If there's just one image, save it directly. if(images.length == 1) { var url = images[0]; var buf = results[0]; var blob = new Blob([results[0]]); var ext = helpers.get_extension(url); var filename = user_info.name + " - " + illust_data.illustId; // If this is a single page of a manga post, include the page number. if(download_type == "image" && illust_data.mangaPages.length > 1) filename += " #" + (manga_page + 1); filename += " - " + illust_data.illustTitle + "." + ext; helpers.save_blob(blob, filename); return; } // There are multiple images, and since browsers are stuck in their own little world, there's // still no way in 2018 to save a batch of files to disk, so ZIP the images. var filenames = []; for(var i = 0; i < images.length; ++i) { var url = images[i]; var blob = results[i]; var ext = helpers.get_extension(url); var filename = i.toString().padStart(3, '0') + "." + ext; filenames.push(filename); } // Create the ZIP. var zip = new create_zip(filenames, results); var filename = user_info.name + " - " + illust_data.illustId + " - " + illust_data.illustTitle + ".zip"; helpers.save_blob(zip, filename); } static is_download_type_available(download_type, illust_data) { // Single image downloading works for single images and manga pages. if(download_type == "image") return illust_data.illustType != 2; // ZIP downloading only makes sense for image sequences. if(download_type == "ZIP") return illust_data.illustType != 2 && illust_data.pageCount > 1; // MJPEG only makes sense for videos. if(download_type == "MKV") return illust_data.illustType == 2; throw "Unknown download type " + download_type; }; static get_download_type_for_image(illust_data) { var download_types = ["image", "ZIP", "MKV"]; for(var type of download_types) if(actions.is_download_type_available(type, illust_data)) return type; return null; } static async load_recent_bookmark_tags() { let url = "https://www.pixiv.net/ajax/user/" + window.global_data.user_id + "/illusts/bookmark/tags"; let result = await helpers.get_request(url, {}); let bookmark_tags = []; let add_tag = (tag) => { // Ignore "untagged". if(tag.tag == "未分類") return; if(bookmark_tags.indexOf(tag.tag) == -1) bookmark_tags.push(tag.tag); } for(let tag of result.body.public) add_tag(tag); for(let tag of result.body.private) add_tag(tag); return bookmark_tags; } } //# sourceURL=https://raw.githubusercontent.com/ppixiv/ppixiv/r119/src/actions.js `; ppixiv.resources["src/muting.js"] = `"use strict"; // This handles querying whether a tag or a user is muted. We don't handle // editing this list currently. ppixiv.muting = class { static get singleton() { if(muting._singleton == null) muting._singleton = new muting(); return muting._singleton; }; constructor() { } set_muted_tags(muted_tags) { this.muted_tags = muted_tags; } set_muted_user_ids(muted_user_ids) { this.muted_user_ids = muted_user_ids; } is_muted_user_id(user_id) { return this.muted_user_ids.indexOf(user_id) != -1; }; // Return true if any tag in tag_list is muted. any_tag_muted(tag_list) { for(var tag of tag_list) { if(tag.tag) tag = tag.tag; if(this.muted_tags.indexOf(tag) != -1) return tag; } return null; } } //# sourceURL=https://raw.githubusercontent.com/ppixiv/ppixiv/r119/src/muting.js `; ppixiv.resources["src/crc32.js"] = `"use strict"; /* pako/lib/zlib/crc32.js, MIT license: https://github.com/nodeca/pako/ */ ppixiv.crc32 = (function() { // Use ordinary array, since untyped makes no boost here function makeTable() { var c, table = []; for(var n =0; n < 256; n++){ c = n; for(var k =0; k < 8; k++){ c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); } table[n] = c; } return table; } // Create table on load. Just 255 signed longs. Not a problem. var crcTable = makeTable(); return function(buf) { var crc = 0; var t = crcTable, end = buf.length; crc = crc ^ (-1); for (var i = 0; i < end; i++ ) { crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; } return (crc ^ (-1)); // >>> 0; }; })(); //# sourceURL=https://raw.githubusercontent.com/ppixiv/ppixiv/r119/src/crc32.js `; ppixiv.resources["src/helpers.js"] = `"use strict"; // This is thrown when an XHR request fails. ppixiv.APIError = class extends Error { constructor(message, url) { super(message); this.url = url; } }; // This is thrown when we disable creating blocked elements. ppixiv.ElementDisabled = class extends Error { }; ppixiv.helpers = { blank_image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", remove_array_element: function(array, element) { let idx = array.indexOf(element); if(idx != -1) array.splice(idx, 1); }, // Preload an array of images. preload_images: function(images) { // We don't need to add the element to the document for the images to load, which means // we don't need to do a bunch of extra work to figure out when we can remove them. var preload = document.createElement("div"); for(var i = 0; i < images.length; ++i) { var img = document.createElement("img"); img.src = images[i]; preload.appendChild(img); } }, move_children: function(parent, new_parent) { for(var child = parent.firstChild; child; ) { var next = child.nextSibling; new_parent.appendChild(child); child = next; } }, remove_elements: function(parent) { while(parent.firstChild !== null) parent.firstChild.remove(); }, // Return true if ancestor is one of descendant's parents, or if descendant is ancestor. is_above(ancestor, descendant) { var node = descendant; while(descendant != null && descendant != ancestor) descendant = descendant.parentNode; return descendant == ancestor; }, create_style: function(css) { var style = document.realCreateElement("style"); style.type = "text/css"; style.textContent = css; return style; }, get_template: function(type) { let template = document.body.querySelector(type); if(template == null) throw "Missing template: " + type; // Replace anyShowing the popup menu when Ctrl is pressed is now optional. \`, }, { version: 112, text: \` Added Send to Tab to the context menu, which allows quickly sending an image to another tab.
Added a More Options dropdown to the popup menu. This includes some things that were previously only available from the hover UI. Send to Tab is also in here.
Disabled the "Similar Illustrations" lightbulb button on thumbnails. It can now be accessed from the popup menu, along with a bunch of other ways to get image recommendations. \` }, { version: 110, text: \` Added Quick View. This views images immediately when the mouse is pressed, and images can be panned with the same press.
This can be enabled in preferences, and may become the default in a future release. \` }, { version: 109, boring: true, text: \`Added a visual marker on thumbnails to show the last image you viewed.\` }, { version: 104, text: "Bookmarks can now be shuffled, to view them in random order. " + "
" + "Bookmarking an image now always likes it, like Pixiv's mobile app. " + "(Having an option for this didn't seem useful.)" + "
" + "Added a Recent History search, to show recent search results. This can be turned " + "off in settings." }, { version: 102, boring: true, text: "Animations now start playing much faster." }, { version: 100, text: "Enabled auto-liking images on bookmark by default, to match the Pixiv mobile apps. " + "If you've previously changed this in preferences, your setting should stay the same." + "
" + "Added a download button for the current page when viewing manga posts." }, { version: 97, text: "Holding Ctrl now displays the popup menu, to make it easier to use for people on touchpads.
" + "
" + "Keyboard hotkeys reworked, and can now be used while hovering over search results.
" + "
" + "Ctrl-V - like image\\n" + "Ctrl-B - bookmark\\n" + "Ctrl-Alt-B - bookmark privately\\n" + "Ctrl-Shift-B - remove bookmark\\n" + "Ctrl-Alt-Shift-M - add bookmark tag\\n" + "Ctrl-F - follow\\n" + "Ctrl-Alt-F - follow privately\\n" + "Ctrl-Shift-F - unfollow\\n" + "" }, { version: 89, text: "Reworked zooming to make it more consistent and easier to use.
" + "
" + "You can now zoom images to 100% to view them at actual size." }, { version: 82, text: "Press Ctrl-Alt-Shift-B to bookmark an image with a new tag." }, { version: 79, text: "Added support for viewing new R-18 works by followed users." }, { version: 77, text: "Added user searching." + "
" + "Commercial/subscription links in user profiles (Fanbox, etc.) now use a different icon." }, { version: 74, text: "Viewing your followed users by tag is now supported." + "
" + "You can now view other people who bookmarked an image, to see what else they've bookmarked. " + "This is available from the top-left hover menu." }, { version: 72, text: "The followed users page now remembers which page you were on if you reload the page, to make " + "it easier to browse your follows if you have a lot of them." + "
" + "Returning to followed users now flashes who you were viewing like illustrations do," + "to make it easier to pick up where you left off." + "
" + "Added a browser back button to the context menu, to make navigation easier in fullscreen " + "when the browser back button isn't available." }, { version: 68, text: "You can now go to either the first manga page or the page list from search results. " + "Click the image to go to the first page, or the page count to go to the page list." + "
" + "Our button is now in the bottom-left when we're disabled, since Pixiv now puts a menu " + "button in the top-left and we were covering it up." }, { version: 65, text: "Bookmark viewing now remembers which page you were on if the page is reloaded." + "
"+ "Zooming is now in smaller increments, to make it easier to zoom to the level you want." }, { version: 57, text: "Search for similar artists. Click the recommendations item at the top of the artist page, " + "or in the top-left when viewing an image." + "
"+ "You can also now view suggested artists." }, { version: 56, text: "Tag translations are now supported. This can be turned off in preferences. " + "
" + "Added quick tag search editing. After searching for a tag, click the edit button " + "to quickly add and remove tags." }, { version: 55, text: "The \\"original\\" view is now available in Rankings." + "
" + "Hiding the mouse cursor can now be disabled in preferences.", }, { version: 49, text: "Add \\"Hover to show UI\\" preference, which is useful for low-res monitors." }, { version: 47, text: "You can now view the users you're following with \\"Followed Users\\". This shows each " + "user's most recent post." }, ]; ppixiv.whats_new = class extends ppixiv.dialog_widget { // Return the newest revision that exists in history. This is always the first // history entry. static latest_history_revision() { return _update_history[0].version; } // Return the latest interesting history entry. // // We won't highlight the "what's new" icon for boring history entries. static latest_interesting_history_revision() { for(let history of _update_history) { if(history.boring) continue; return history.version; } // We shouldn't get here. throw Error("Couldn't find anything interesting"); } constructor({...options}) { super({...options, visible: true, template: \`