NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Hitomi - Search & UI Tweaks // @namespace brazenvoid // @version 6.0.1 // @author brazenvoid // @license GPL-3.0-only // @description Various search filters and user experience enhancers // @match https://hitomi.la/* // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js // @require https://greasyfork.org/scripts/375557-base-brazen-resource/code/Base%20Brazen%20Resource.js?version=1244990 // @require https://greasyfork.org/scripts/416104-brazen-ui-generator/code/Brazen%20UI%20Generator.js?version=1245364 // @require https://greasyfork.org/scripts/418665-brazen-configuration-manager/code/Brazen%20Configuration%20Manager.js?version=1245040 // @require https://greasyfork.org/scripts/429587-brazen-item-attributes-resolver/code/Brazen%20Item%20Attributes%20Resolver.js?version=1244644 // @require https://greasyfork.org/scripts/416105-brazen-base-search-enhancer/code/Brazen%20Base%20Search%20Enhancer.js?version=1245401 // @grant GM_addStyle // @run-at document-end // ==/UserScript== GM_addStyle(`#settings-wrapper{min-width:450px;width:450px}.disliked-tag{background-color:lightcoral !important}.disliked-tag:hover{background-color:indianred !important}.disliked-tag.favourite-tag{background-color:orange !important}.disliked-tag.favourite-tag:hover{background-color:darkorange !important}.favourite-tag{background-color:mediumseagreen !important}.favourite-tag:hover{background-color:forestgreen !important}`) const IS_GALLERY_PAGE = $('#dl-button').length const FILTER_GALLERY_TYPES = 'Show Gallery Types' const FILTER_PAGES = 'Pages' const FILTER_LANGUAGES = 'Languages' const OPTION_REMOVE_RELATED_GALLERIES = 'Remove Related Galleries' const UI_FAVOURITE_TAGS = 'Favourite Tags' const UI_DISLIKED_TAGS = 'Disliked Tags' const UI_SHOW_ALL_TAGS = 'Show All Gallery Tags' class HitomiSearchAndUITweaks extends BrazenBaseSearchEnhancer { constructor() { super({ isUserLoggedIn: false, itemDeepAnalysisSelector: '', itemLinkSelector: '', itemListSelectors: '.gallery-content', itemNameSelector: 'h1.lillie a', itemSelectors: '.acg,.anime,.cg,.dj,.manga', requestDelay: 0, scriptPrefix: 'hitomi-sui-', tagSelectorGenerator: (tag) => { let selector tag = encodeURIComponent(tag.trim()) if (tag.startsWith('artist%3A')) { selector = 'a[href="/artist/' + tag.replace('artist%3A', '') + '-all.html"]' } else if (tag.startsWith('series%3A')) { selector = 'a[href="/series/' + tag.replace('series%3A', '') + '-all.html"]' } else { selector = 'a[href="/tag/' + tag + '-all.html"]' } return selector } }) this._setupFeatures() this._setupUI() this._setupEvents() } /** * @private */ _setupEvents() { if (IS_GALLERY_PAGE) { this._onBeforeUIBuild.push(() => this._performComplexOperation( FILTER_PAGES, (range) => !this._getConfig(OPTION_DISABLE_COMPLIANCE_VALIDATION) && this._configurationManager.generateValidationCallback(FILTER_PAGES)(range), (range) => { let navPages = $('.simplePagerNav li').length let pageCount = navPages > 0 ? navPages * 50 : $('.simplePagerPage1').length if (!Validator.isInRange(pageCount, range.minimum, range.maximum)) { top.close() } }) ) this._onBeforeUIBuild.push(() => this._performOperation( OPTION_REMOVE_RELATED_GALLERIES, () => $('.gallery-content').remove())) } this._onAfterUIBuild.push(() => this._uiGen.getSelectedSection()[0].userScript = this) this._onFirstHitAfterCompliance.push((item) => { this._performComplexOperation(UI_SHOW_ALL_TAGS, (flag) => flag && !IS_GALLERY_PAGE, () => { let tags = item.find('.relatedtags > ul > li') let lastTag = tags.last() if (lastTag.text() === '...') { lastTag.remove() tags.filter('.hidden-list-item').removeClass('hidden-list-item') } }) }) } /** * @private */ _setupFeatures() { this._configurationManager .addCheckboxesGroup(FILTER_GALLERY_TYPES, [ ['Anime', 'anime'], ['Artist CG', 'acg'], ['Doujinshi', 'dj'], ['Game CG', 'cg'], ['Manga', 'manga'], ], 'Show only selected gallery types.') .addCheckboxesGroup(FILTER_LANGUAGES, [ ['N/A', 'not-applicable'], ['Japanese', 'japanese'], ['Chinese', 'chinese'], ['English', 'english'], ['Albanian', 'albanian'], ['Arabic', 'arabic'], ['Bulgarian', 'bulgarian'], ['Catalan', 'catalan'], ['Cebuano', 'cebuano'], ['Czech', 'czech'], ['Danish', 'danish'], ['Dutch', 'dutch'], ['Esperanto', 'esperanto'], ['Estonian', 'estonian'], ['Finnish', 'finnish'], ['French', 'french'], ['German', 'german'], ['Greek', 'greek'], ['Hebrew', 'hebrew'], ['Hungarian', 'hungarian'], ['Indonesian', 'indonesian'], ['Italian', 'italian'], ['Korean', 'korean'], ['Latin', 'latin'], ['Mongolian', 'mongolian'], ['Norwegian', 'norwegian'], ['Persian', 'persian'], ['Polish', 'polish'], ['Portuguese', 'portuguese'], ['Romanian', 'romanian'], ['Russian', 'russian'], ['Slovak', 'slovak'], ['Spanish', 'spanish'], ['Swedish', 'swedish'], ['Tagalog', 'tagalog'], ['Thai', 'thai'], ['Turkish', 'turkish'], ['Ukrainian', 'ukrainian'], ['Unspecified', 'unspecified'], ['Vietnamese', 'vietnamese'], ], 'Select languages to show') .addFlagField(OPTION_REMOVE_RELATED_GALLERIES, 'Remove related galleries section from gallery pages.') .addFlagField(UI_SHOW_ALL_TAGS, 'Show all gallery tags in search results.') .addRangeField(FILTER_PAGES, 0, Infinity, 'Close gallery pages that don\'t satisfy these page limits. Only works on galleries opened in new tabs.') this._addItemComplianceFilter(FILTER_LANGUAGES, (item, valueKeys) => { let languageLink = item.find('tr:nth-child(3) > td:nth-child(2) a') if (languageLink.length) { languageLink = languageLink.attr('href') for (let key of valueKeys) { if (languageLink.includes(key)) { return true } } return false } return valueKeys.includes('not-applicable') }) this._addItemComplianceFilter(FILTER_GALLERY_TYPES, (item, valueKeys) => { for (let galleryClass of valueKeys) { if (item.hasClass(galleryClass)) { return true } } return false }) let otherTagSections = IS_GALLERY_PAGE ? $('.tags') : null this._addItemTagHighlights(UI_FAVOURITE_TAGS, otherTagSections, 'favourite-tag', 'Specify favourite tags to highlight. "&" "|" can be used.') this._addItemTagHighlights(UI_DISLIKED_TAGS, otherTagSections, 'disliked-tag', 'Specify disliked tags to highlight. "&" "|" can be used.') this._addItemTagBlacklistFilter(10) } /** * @private */ _setupUI() { this._userInterface = [ this._uiGen.createTabsSection(['Filters', 'Blacklist', 'Highlights', 'Languages', 'Global', 'Stats'], [ this._uiGen.createTabPanel('Filters', true).append([ this._configurationManager.createElement(FILTER_GALLERY_TYPES), this._uiGen.createSeparator(), this._configurationManager.createElement(FILTER_PAGES), ]), this._uiGen.createTabPanel('Blacklist').append([ this._configurationManager.createElement(OPTION_ENABLE_BLACKLIST), this._configurationManager.createElement(FILTER_TAG_BLACKLIST), ]), this._uiGen.createTabPanel('Highlights').append([ this._configurationManager.createElement(UI_FAVOURITE_TAGS), this._configurationManager.createElement(UI_DISLIKED_TAGS), ]), this._uiGen.createTabPanel('Languages').append([ this._configurationManager.createElement(FILTER_LANGUAGES), ]), this._uiGen.createTabPanel('Global').append([ this._configurationManager.createElement(UI_SHOW_ALL_TAGS), this._configurationManager.createElement(OPTION_ALWAYS_SHOW_SETTINGS_PANE), this._uiGen.createSeparator(), this._createSettingsBackupRestoreFormActions(), ]), this._uiGen.createTabPanel('Stats').append([ this._uiGen.createStatisticsFormGroup(FILTER_GALLERY_TYPES), this._uiGen.createStatisticsFormGroup(FILTER_LANGUAGES), this._uiGen.createStatisticsFormGroup(FILTER_TAG_BLACKLIST), this._uiGen.createSeparator(), this._uiGen.createStatisticsTotalsGroup(), ]), ]), this._configurationManager.createElement(OPTION_DISABLE_COMPLIANCE_VALIDATION), this._uiGen.createSeparator(), this._createSettingsFormActions(), this._uiGen.createSeparator(), this._uiGen.createStatusSection(), ] } } (new HitomiSearchAndUITweaks).init()