- // ==UserScript==
- // @name Hitomi - Search & UI Tweaks
- // @namespace brazenvoid
- // @version 6.1.2
- // @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://update.greasyfork.org/scripts/375557/1244990/Base%20Brazen%20Resource.js
- // @require https://update.greasyfork.org/scripts/416104/1371950/Brazen%20UI%20Generator.js
- // @require https://update.greasyfork.org/scripts/418665/1245040/Brazen%20Configuration%20Manager.js
- // @require https://update.greasyfork.org/scripts/429587/1244644/Brazen%20Item%20Attributes%20Resolver.js
- // @require https://update.greasyfork.org/scripts/416105/1300196/Brazen%20Base%20Search%20Enhancer.js
- // @grant GM_addStyle
- // @run-at document-end
- // ==/UserScript==
-
- GM_addStyle(
- `#settings-wrapper{min-width:400px;width:400px}.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'
-
- const ITEM_GALLERY_TYPE = 'Gallery Type'
- const ITEM_LANGUAGE = 'Language'
-
- class HitomiSearchAndUITweaks extends BrazenBaseSearchEnhancer
- {
- constructor()
- {
- super({
- isUserLoggedIn: false,
- itemDeepAnalysisSelector: '',
- itemLinkSelector: '',
- itemListSelectors: '.gallery-content',
- itemNameSelector: 'h1.lillie a',
- itemSelectors: '.anime,.acg,.dj,.cg,.imageset,.manga',
- requestDelay: 0,
- scriptPrefix: 'hitomi-sui-',
- tagSelectorGenerator: (tag) => {
- let selector
- tag = encodeURIComponent(tag.trim()).replace('-', '%2D')
-
- 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'],
- ['Image Set', 'imageset'],
- ['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._itemAttributesResolver
- .addAttribute(ITEM_GALLERY_TYPE, (item) => item.attr('class'))
- .addAttribute(ITEM_LANGUAGE, (item) => {
- let link = item.find('tr:nth-child(3) > td:nth-child(2) a')
- if (link.length) {
- return link.attr('href').replace('/index-', '').replace('.html', '')
- }
- return 'not-applicable'
- })
-
- this._addItemComplianceFilter(FILTER_LANGUAGES, ITEM_LANGUAGE)
- this._addItemComplianceFilter(FILTER_GALLERY_TYPES, ITEM_GALLERY_TYPE)
-
- 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(8)
- }
-
- /**
- * @private
- */
- _setupUI()
- {
- this._userInterface = [
- this._uiGen.createTabsSection(['Filters', '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.createSeparator(),
- this._configurationManager.createElement(OPTION_ENABLE_TAG_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()