Video Celebs Search And UI Tweaks

Video filters and UI manipulations

Från och med 2020-11-13. Se den senaste versionen.

// ==UserScript==
// @name         Video Celebs Search And UI Tweaks
// @version      1.0.0
// @namespace    brazenvoid
// @author       brazenvoid
// @license      GPL-3.0-only
// @description  Video filters and UI manipulations
// @include      https://videocelebs.net/*
// @require      https://greasyfork.org/scripts/375557-base-resource/code/Base%20Resource.js?version=854444
// @grant        GM_addStyle
// @run-at       document-end
// ==/UserScript==

GM_addStyle(`.form-group{display:flex}label.form-label{flex-grow:1}input.form-input{height:auto}input.form-input.check-radio-input{width:auto;margin:0 5px 1px 0}label.form-label{padding: 0}label.title{margin: 0}div.form-group.form-range-input-group>input+input{margin-left: 5px;margin-right:0}`)

const PAGE_PATH_NAME = window.location.pathname

const IS_VIDEO_PAGE = PAGE_PATH_NAME.endsWith('.html')

const FILTER_RATING_VIDEOS_KEY = 'Rating'
const FILTER_VIDEOS_YEAR_KEY = 'Year'

const OPTION_ALWAYS_SHOW_UI = 'Always Show This Settings Pane'
const OPTION_DISABLE_VIDEO_FILTERS = 'Disable All Video Filters'
const OPTION_MOVE_VIDEO_ATTRIBUTES_SECTION_KEY = 'Reposition Attributes Section'
const OPTION_REMOVE_COMMENTS_SECTION_KEY = 'Remove Comments Section'
const OPTION_REMOVE_IFRAME_SECTION_KEY = 'Remove Iframe Share Section'
const OPTION_REMOVE_RELATED_VIDEOS_SECTION_KEY = 'Remove Related Videos Section'

class VideoCelebsSearchAndUITweaks extends BaseHandler
{
    /**
     * @typedef {{disableItemComplianceValidation: boolean, rating: {maximum: number, minimum: number}, year: {maximum: number, minimum: number},
     *     moveVideoAttributesBelowDescription: boolean, removeCommentsSection: boolean, removeIFrameSection: boolean, removeRelatedVideosSection: boolean, showUIAlways: boolean
     *     }} VideoCelebsSearchAndUITweaksSettings
     */

    static initialize ()
    {
        return (new VideoCelebsSearchAndUITweaks).init()
    }

    constructor ()
    {
        super('vc-sui-', 'item.big', {
            rating: {
                minimum: 0,
                maximum: 0,
            },
            year: {
                minimum: 0,
                maximum: 0,
            },
            moveVideoAttributesBelowDescription: false,
            removeCommentsSection: false,
            removeIFrameSection: false,
            removeRelatedVideosSection: false,
        })

        // UI Events

        this._onBeforeUIBuild = () => {
            if (IS_VIDEO_PAGE) {
                this._moveVideoAttributesBelowDescription()
                this._removeCommentsSection()
                this._removeIFrameSection()
                this._removeRelatedVideosSection()
            }
        }

        this._onUIBuild = () =>
            this._uiGen.createSection('settings', '#ffa31a', '15vh', '250px').addSectionChildren([
                this._uiGen.createTabsSection(['Filters', 'UI', 'Stats'], [
                    this._uiGen.createTabPanel('Filters', [
                        this._createFormRangeInputGroup(FILTER_RATING_VIDEOS_KEY, 'number'),
                        this._createFormRangeInputGroup(FILTER_VIDEOS_YEAR_KEY, 'number'),
                        this._uiGen.createSeparator(),
                        this._uiGen.createFormInputGroup(OPTION_DISABLE_VIDEO_FILTERS, 'checkbox', 'Disables all video filters.'),
                        this._uiGen.createSeparator(),
                        this._createSettingsFormActions(),
                        this._uiGen.createSeparator(),
                        this._uiGen.createStoreFormSection(this._settingsStore),
                    ]),
                    this._uiGen.createTabPanel('UI', [
                        this._uiGen.createFormInputGroup(OPTION_MOVE_VIDEO_ATTRIBUTES_SECTION_KEY, 'checkbox', 'Move the video attributes section from below the screenshot area to under the description.'),
                        this._uiGen.createFormInputGroup(OPTION_REMOVE_COMMENTS_SECTION_KEY, 'checkbox', 'Remove comments area on video pages.'),
                        this._uiGen.createFormInputGroup(OPTION_REMOVE_IFRAME_SECTION_KEY, 'checkbox', 'Remove iframe share section under video player.'),
                        this._uiGen.createFormInputGroup(OPTION_REMOVE_RELATED_VIDEOS_SECTION_KEY, 'checkbox', 'Remove related videos section on video pages.'),
                        this._uiGen.createSeparator(),
                        this._uiGen.createFormInputGroup(OPTION_ALWAYS_SHOW_UI, 'checkbox', 'Always show this interface.'),
                        this._uiGen.createSeparator(),
                        this._createSettingsFormActions(),
                        this._uiGen.createSeparator(),
                        this._uiGen.createStoreFormSection(this._settingsStore),
                    ]),
                    this._uiGen.createTabPanel('Stats', [
                        this._uiGen.createStatisticsFormGroup(FILTER_RATING_VIDEOS_KEY),
                        this._uiGen.createStatisticsFormGroup(FILTER_VIDEOS_YEAR_KEY),
                        this._uiGen.createSeparator(),
                        this._uiGen.createStatisticsTotalsGroup(),
                    ]),
                ]),
                this._uiGen.createStatusSection(),
            ])

        // Compliance Events

        this._onGetItemLists = () => document.querySelectorAll('.midle_div,.list_videos')

        this._complianceFilters = [
            (videoItem) => this._validateRating(videoItem),
            (videoItem) => this._validateYear(videoItem),
        ]

        // Store Events

        this._onSettingsStoreUpdate = () => {

            /** @type {VideoCelebsSearchAndUITweaksSettings} */
            let store = this._settingsStore.get()

            this._uiGen.setSettingsInputCheckedStatus(OPTION_ALWAYS_SHOW_UI, store.showUIAlways)
            this._uiGen.setSettingsInputCheckedStatus(OPTION_DISABLE_VIDEO_FILTERS, store.disableItemComplianceValidation)
            this._uiGen.setSettingsInputCheckedStatus(OPTION_MOVE_VIDEO_ATTRIBUTES_SECTION_KEY, store.moveVideoAttributesBelowDescription)
            this._uiGen.setSettingsInputCheckedStatus(OPTION_REMOVE_COMMENTS_SECTION_KEY, store.removeCommentsSection)
            this._uiGen.setSettingsInputCheckedStatus(OPTION_REMOVE_IFRAME_SECTION_KEY, store.removeIFrameSection)
            this._uiGen.setSettingsInputCheckedStatus(OPTION_REMOVE_RELATED_VIDEOS_SECTION_KEY, store.removeRelatedVideosSection)

            this._uiGen.setSettingsRangeInputValue(FILTER_RATING_VIDEOS_KEY, store.rating.minimum, store.rating.maximum)
            this._uiGen.setSettingsRangeInputValue(FILTER_VIDEOS_YEAR_KEY, store.year.minimum, store.year.maximum)
        }

        this._onSettingsApply = () => {

            /** @type {VideoCelebsSearchAndUITweaksSettings} */
            let settings = this._settings

            settings.disableItemComplianceValidation = this._uiGen.getSettingsInputCheckedStatus(OPTION_DISABLE_VIDEO_FILTERS)
            settings.moveVideoAttributesBelowDescription = this._uiGen.getSettingsInputCheckedStatus(OPTION_MOVE_VIDEO_ATTRIBUTES_SECTION_KEY)
            settings.rating.minimum = this._uiGen.getSettingsRangeInputValue(FILTER_RATING_VIDEOS_KEY, true)
            settings.rating.maximum = this._uiGen.getSettingsRangeInputValue(FILTER_RATING_VIDEOS_KEY, false)
            settings.removeCommentsSection = this._uiGen.getSettingsInputCheckedStatus(OPTION_REMOVE_COMMENTS_SECTION_KEY)
            settings.removeIFrameSection = this._uiGen.getSettingsInputCheckedStatus(OPTION_REMOVE_IFRAME_SECTION_KEY)
            settings.removeRelatedVideosSection = this._uiGen.getSettingsInputCheckedStatus(OPTION_REMOVE_RELATED_VIDEOS_SECTION_KEY)
            settings.showUIAlways = this._uiGen.getSettingsInputCheckedStatus(OPTION_ALWAYS_SHOW_UI)
            settings.year.minimum = this._uiGen.getSettingsRangeInputValue(FILTER_VIDEOS_YEAR_KEY, true)
            settings.year.maximum = this._uiGen.getSettingsRangeInputValue(FILTER_VIDEOS_YEAR_KEY, false)
        }
    }

    _moveVideoAttributesBelowDescription ()
    {
        if (this._settings.moveVideoAttributesBelowDescription) {
            let videoInfoBlock = document.querySelector('.entry-utility')
            videoInfoBlock.parentNode.insertBefore(videoInfoBlock, videoInfoBlock.previousSibling.previousSibling)
        }
    }

    _removeCommentsSection ()
    {
        if (this._settings.removeCommentsSection) {
            document.querySelector('.comments-area').remove()
        }
    }

    _removeIFrameSection ()
    {
        if (this._settings.removeIFrameSection) {
            document.querySelector('#tab_share').remove()
        }
    }

    _removeRelatedVideosSection ()
    {
        if (this._settings.removeRelatedVideosSection) {
            document.querySelector('.related').remove()
        }
    }

    /**
     * Validate video source release year
     * @param {Node|HTMLElement} videoItem
     * @return {boolean}
     * @private
     */
    _validateRating (videoItem)
    {
        if (this._settings.rating.minimum > 0 || this._settings.rating.maximum > 0) {
            let rating = parseInt(videoItem.querySelector('.rating').textContent.trim().replace('%', ''))
            return this._validator.validateRange(FILTER_RATING_VIDEOS_KEY, rating, [this._settings.rating.minimum, this._settings.rating.maximum])
        }
        return true
    }

    /**
     * Validate video view count
     * @param {Node|HTMLElement} videoItem
     * @return {boolean}
     * @private
     */
    _validateYear (videoItem)
    {
        if (this._settings.year.minimum > 0 || this._settings.year.maximum > 0) {
            let yearFragments = videoItem.querySelector('.title a').textContent.trim().split('(')
            let year = parseInt(yearFragments[yearFragments.length - 1].replace(')', ''))
            return this._validator.validateRange(FILTER_RATING_VIDEOS_KEY, year, [this._settings.year.minimum, this._settings.year.maximum])
        }
        return true
    }

    /**
     * @param {string} label
     * @param {string} inputsType
     *
     * @return {HTMLElement}
     * @private
     */
    _createFormRangeInputGroup (label, inputsType = 'text')
    {
        let maxInputSelector = this._uiGen._selectorGenerator.getSettingsRangeInputSelector(label, false)
        let minInputSelector = this._uiGen._selectorGenerator.getSettingsRangeInputSelector(label, true)

        let divFormInputGroup = this._uiGen.createFormGroup([
            this._uiGen.createFormGroupLabel(label, '', inputsType),
            this._uiGen.createFormGroupInput(minInputSelector, inputsType),
            this._uiGen.createFormGroupInput(maxInputSelector, inputsType),
        ])
        divFormInputGroup.classList.add('form-range-input-group')

        return divFormInputGroup
    }
}

VideoCelebsSearchAndUITweaks.initialize()