// ==UserScript== // @name B站合集倒序播放 // @description 增强B站功能,支持视频合集倒序播放,还有一些其他小功能 // @version 0.0.3 // @author Grant Howard, Coulomb-G // @copyright 2024, Grant Howard // @license MIT // @match *://*.bilibili.com/video/* // @exclude *://api.bilibili.com/* // @exclude *://api.*.bilibili.com/* // @exclude *://*.bilibili.com/api/* // @exclude *://member.bilibili.com/studio/bs-editor/* // @exclude *://t.bilibili.com/h5/dynamic/specification // @exclude *://bbq.bilibili.com/* // @exclude *://message.bilibili.com/pages/nav/header_sync // @exclude *://s1.hdslb.com/bfs/seed/jinkela/short/cols/iframe.html // @exclude *://open-live.bilibili.com/* // @run-at document-start // @grant unsafeWindow // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_info // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_addStyle // @connect raw.githubusercontent.com // @connect github.com // @connect cdn.jsdelivr.net // @connect cn.bing.com // @connect www.bing.com // @connect translate.google.cn // @connect translate.google.com // @connect localhost // @connect * // @icon https://cdn.jsdelivr.net/gh/the1812/Bilibili-Evolved@preview/images/logo-small.png // @icon64 https://cdn.jsdelivr.net/gh/the1812/Bilibili-Evolved@preview/images/logo.png // @namespace https://greasyfork.org/users/734541 // @downloadURL none // ==/UserScript== (() => { GM_addStyle(`#zaizai-div .video-sections-head_second-line { display: flex; flex-wrap: wrap; align-items: center; margin: 12px 16px 0; color: var(--text3); color: var(--text3); padding-bottom: 12px; font-size: 14px; line-height: 16px; gap: 10px 20px; } #zaizai-div .border-bottom-line { height: 1px; background: var(--line_regular); margin: 0 15px; } #zaizai-div .switch-button { margin: 0; display: inline-block; position: relative; width: 30px; height: 20px; border: 1px solid #ccc; outline: none; border-radius: 10px; box-sizing: border-box; background: #ccc; cursor: pointer; transition: border-color .2s, background-color .2s; vertical-align: middle; } #zaizai-div .switch-button.on:after { left: 11px; } #zaizai-div .switch-button:after { content: ""; position: absolute; top: 1px; left: 1px; border-radius: 100%; width: 16px; height: 16px; background-color: #fff; transition: all .2s; } #zaizai-div .switch-button.on { border: 1px solid var(--brand_blue); background-color: var(--brand_blue); } #zaizai-div .txt { margin-right: 4px; vertical-align: middle; } `) const console = (() => { const _console = window.console return { log: (...args) => { _console.log(`%c ZAIZAI `, 'padding: 2px 1px; border-radius: 3px; color: #fff; background: #42c02e; font-weight: bold;', ...args) } } })() // 全局变量 const local = useReactiveLocalStorage({ defaultreverseorder: false, // 开启倒序播放 startreverseorder: false, addsectionslistheigth: false }) let Video = null let videoSections = null function useReactiveLocalStorage(obj) { let data = {} let zaizaiStore = window.localStorage.getItem('zaizai-store') if (zaizaiStore) { zaizaiStore = JSON.parse(zaizaiStore) for (const key in obj) { data[key] = zaizaiStore[key] || obj[key] } } else { data = obj } let handler = { set(target, key, value) { let res = Reflect.set(target, key, value) try { window.localStorage.setItem(`zaizai-store`, JSON.stringify(data)) } catch (error) { console.log('存储失败,请检查浏览器设置', error); } return res }, get(target, key) { let ret = Reflect.get(target, key) return typeof ret === 'object' ? new Proxy(ret, handler) : ret } } data = new Proxy(data, handler) return data } function waitTime(callback, options = { time: 500, isSetup: false }) { let timeout = null return new Promise((resolve) => { if (options.isSetup) { let res = callback() if (res) resolve(res) } timeout = setInterval(() => { let res = callback() if (res) { clearInterval(timeout) resolve(res) } }, options.time) }) } async function selectVideo() { await waitTime(() => { let video = document.querySelector('video') if (video) { Video = video return true } }, { isSetup: true }) } async function switchAddsectionslistheigthOnClick(action) { if (typeof action !== 'string') { local.addsectionslistheigth = !local.addsectionslistheigth } const ListEl = await waitTime(() => { return document.querySelector('.video-sections-content-list') }, { isSetup: true }) if (local.addsectionslistheigth) { typeof action !== 'string' && this.classList.add('on') ListEl.style.maxHeight = '40vh' ListEl.style.height = '40vh' } else { typeof action !== 'string' && this.classList.remove('on') ListEl.style.height = '150px' ListEl.style.maxHeight = '150px' } } async function VideoOnPlay() { if (local.startreverseorder && !document.querySelector('#zaizai-div')) { const div = document.createElement('div') div.id = 'zaizai-div' div.innerHTML = `