BiliBili动态隐藏

根据Up主名称,在动态页进行筛选,隐藏屏蔽的Up主动态。

目前为 2023-07-23 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name BiliBili动态隐藏
  3. // @author Yiero
  4. // @description 根据Up主名称,在动态页进行筛选,隐藏屏蔽的Up主动态。
  5. // @version 1.4.5
  6. // @namespace https://github.com/AliubYiero/TamperMonkeyScripts
  7. // @match https://t.bilibili.com/*
  8. // @icon https://t.bilibili.com/favicon.ico
  9. // @resource layuiCss https://cdn.staticfile.org/layui/2.8.11/css/layui.min.css
  10. // @license GPL
  11. // @grant GM_registerMenuCommand
  12. // @grant GM_unregisterMenuCommand
  13. // @grant GM_addStyle
  14. // @grant GM_getResourceText
  15. // @run-at document-start
  16. // @updateUrl https://raw.githubusercontent.com/AliubYiero/TamperMonkeyScripts/master/dist/HideDynamic.js
  17. // @downloadUrl https://raw.githubusercontent.com/AliubYiero/TamperMonkeyScripts/master/dist/HideDynamic.js
  18. // ==/UserScript==
  19. GM_addStyle( GM_getResourceText( 'layuiCss' ) )
  20.  
  21. var __defProp = Object.defineProperty;
  22. var __defNormalProp = ( obj, key, value ) => key in obj ? __defProp( obj, key, {
  23. enumerable: true,
  24. configurable: true,
  25. writable: true,
  26. value
  27. } ) : obj[key] = value;
  28. var __publicField = ( obj, key, value ) => {
  29. __defNormalProp( obj, typeof key !== "symbol" ? key + "" : key, value );
  30. return value;
  31. };
  32.  
  33. function getElement( parent, selector, timeout = 0 ) {
  34. return new Promise( ( resolve ) => {
  35. let result = parent.querySelector( selector );
  36. if ( result ) {
  37. return resolve( result );
  38. }
  39. let timer;
  40. const mutationObserver = window.MutationObserver || window.WebkitMutationObserver || window.MozMutationObserver;
  41. if ( mutationObserver ) {
  42. const observer = new mutationObserver( ( mutations ) => {
  43. for ( let mutation of mutations ) {
  44. for ( let addedNode of mutation.addedNodes ) {
  45. if ( addedNode instanceof Element ) {
  46. result = addedNode.matches( selector ) ? addedNode : addedNode.querySelector( selector );
  47. if ( result ) {
  48. observer.disconnect();
  49. timer && clearTimeout( timer );
  50. return resolve( result );
  51. }
  52. }
  53. }
  54. }
  55. } );
  56. observer.observe( parent, {
  57. childList: true,
  58. subtree: true
  59. } );
  60. if ( timeout > 0 ) {
  61. timer = setTimeout( () => {
  62. observer.disconnect();
  63. return resolve( null );
  64. }, timeout );
  65. }
  66. }
  67. else {
  68. const listener = ( e ) => {
  69. if ( e.target instanceof Element ) {
  70. result = e.target.matches( selector ) ? e.target : e.target.querySelector( selector );
  71. if ( result ) {
  72. parent.removeEventListener( "DOMNodeInserted", listener, true );
  73. timer && clearTimeout( timer );
  74. return resolve( result );
  75. }
  76. }
  77. };
  78. parent.addEventListener( "DOMNodeInserted", listener, true );
  79. if ( timeout > 0 ) {
  80. timer = setTimeout( () => {
  81. parent.removeEventListener( "DOMNodeInserted", listener, true );
  82. return resolve( null );
  83. }, timeout );
  84. }
  85. }
  86. } );
  87. }
  88.  
  89. const registerMenu = ( title, callback ) => {
  90. GM_registerMenuCommand( title, function () {
  91. callback();
  92. } );
  93. };
  94. const createElement = ( elementConfig ) => {
  95. const { tagName, className, id, innerHTML, innerText } = elementConfig;
  96. const element = document.createElement( tagName );
  97. if ( className && typeof className === "string" ) {
  98. element.classList.add( className );
  99. }
  100. else if ( className && Array.isArray( className ) ) {
  101. element.classList.add( ...className );
  102. }
  103. if ( id ) {
  104. element.id = id;
  105. }
  106. if ( innerHTML ) {
  107. element.innerHTML = innerHTML;
  108. }
  109. if ( innerText ) {
  110. element.innerText = innerText;
  111. }
  112. for ( let elementConfigKey in elementConfig ) {
  113. if ( [ "tagName", "className", "id", "innerHTML", "innerText" ].indexOf( elementConfigKey ) !== -1 ) {
  114. continue;
  115. }
  116. element.setAttribute( elementConfigKey, elementConfig[elementConfigKey] );
  117. }
  118. return element;
  119. };
  120. const addElementToDocument = ( element, cssString, fatherElement = document.body ) => {
  121. fatherElement.append( element );
  122. GM_addStyle( cssString );
  123. };
  124. const addStyle = ( cssString ) => {
  125. GM_addStyle( cssString );
  126. };
  127.  
  128. class Info {
  129. constructor( projectName ) {
  130. // @ts-ignore
  131. __publicField( this, "projectName" );
  132. __publicField( this, "header" );
  133. this.projectName = projectName;
  134. this.header = `[${ projectName }]`;
  135. }
  136. log( ...msg ) {
  137. /* @__PURE__ */
  138. ( () => {
  139. } )( ...this.contentInfo( ...msg ) );
  140. }
  141. info( ...msg ) {
  142. console.info( ...this.contentInfo( ...msg ) );
  143. }
  144. warn( ...msg ) {
  145. console.warn( ...this.contentInfo( ...msg ) );
  146. }
  147. error( ...msg ) {
  148. console.error( ...this.contentInfo( ...msg ) );
  149. }
  150. contentInfo( ...msg ) {
  151. return [ this.header, ...msg ];
  152. }
  153. }
  154.  
  155. function importLayui() {
  156. let script = document.createElement( "script" );
  157. script.type = "text/javascript";
  158. script.src = "https://cdn.staticfile.org/layui/2.8.11/layui.min.js";
  159. document.head.appendChild( script );
  160. }
  161.  
  162. class Sleep {
  163. /** 延时睡眠等待 */
  164. static time( delay = 1 ) {
  165. return new Promise( ( resolve ) => {
  166. setTimeout( resolve, delay * 1e3 );
  167. } );
  168. }
  169. /** 页面加载等待 */
  170. static windowLoad( delay = 0 ) {
  171. return new Promise( ( resolve ) => {
  172. window.addEventListener( "load", () => {
  173. setTimeout( resolve, delay * 1e3 );
  174. } );
  175. } );
  176. }
  177. }
  178.  
  179. class Data {
  180. /** @param {array} newData */
  181. constructor( newData ) {
  182. /** @type {Map<string, {id: string, isBandLive: boolean, isBandDynamic: boolean, isBandVideo: boolean}>} */
  183. __publicField( this, "data" );
  184. __publicField( this, "originData" );
  185. if ( newData ) {
  186. this.setToLocalStorage( this.arrayToMap( newData ) );
  187. }
  188. this.getFromLocalStorage();
  189. }
  190. /** 防止多余数据提交到data中,进行重新赋值 */
  191. limitValue( obj ) {
  192. const { id, isBandLive, isBandDynamic, isBandVideo } = obj;
  193. return {
  194. id,
  195. isBandLive: isBandLive || false,
  196. isBandDynamic: isBandDynamic || false,
  197. isBandVideo: isBandVideo || false
  198. };
  199. }
  200. /** 添加一个对象 */
  201. set( newObj ) {
  202. if ( this.data.has( newObj.id ) ) {
  203. return;
  204. }
  205. const limitData = this.limitValue( newObj );
  206. this.data.set( newObj.id, limitData );
  207. this.setToLocalStorage();
  208. return limitData;
  209. }
  210. /** 更新其中一个对象 */
  211. update( newObj ) {
  212. const limitData = this.limitValue( newObj );
  213. this.data.set( newObj.id, limitData );
  214. this.setToLocalStorage();
  215. }
  216. /** 删除其中一个对象 */
  217. delete( newObjOrId ) {
  218. if ( typeof newObjOrId === "string" ) {
  219. this.data.delete( newObjOrId );
  220. }
  221. else {
  222. this.data.delete( newObjOrId.id );
  223. }
  224. this.setToLocalStorage();
  225. }
  226. /** 改变其中一个对象的键(删除原对象,建立新对象) */
  227. change( newObj, oldObjOrId ) {
  228. this.delete( oldObjOrId );
  229. this.set( this.limitValue( newObj ) );
  230. this.setToLocalStorage();
  231. }
  232. /** 从localStorage中获取data */
  233. getFromLocalStorage() {
  234. this.originData = JSON.parse( localStorage.getItem( "bandList" ) || "[]" );
  235. this.data = this.arrayToMap( this.originData );
  236. }
  237. /** 将data设置到localStorage中 */
  238. setToLocalStorage( value = this.data ) {
  239. localStorage.setItem( "bandList", JSON.stringify( this.mapToArray( value ) ) );
  240. }
  241. /**
  242. * 数组转Map
  243. * @param {{id: string, [propName: string]: any}[]} array
  244. * @return {Map}
  245. * */
  246. arrayToMap( array ) {
  247. const map = /* @__PURE__ */ new Map();
  248. array.forEach( ( value ) => {
  249. value.id = value.id.trim();
  250. map.set( value.id, value );
  251. } );
  252. return map;
  253. }
  254. /**
  255. * Map转数组
  256. * @param {Map} map
  257. * @return {any[]}
  258. * */
  259. mapToArray( map ) {
  260. const array = [];
  261. for ( let value of map.values() ) {
  262. array.push( value );
  263. }
  264. return array;
  265. }
  266. }
  267.  
  268. class UiEvent {
  269. constructor( data ) {
  270. __publicField( this, "data" );
  271. __publicField( this, "treeTable" );
  272. __publicField( this, "domList" );
  273. this.data = data;
  274. this.treeTable = layui.treeTable;
  275. this.domList = {
  276. main: void 0
  277. };
  278. this.getMainDom();
  279. }
  280. /** 添加数据 */
  281. add( res ) {
  282. const addData = ( res2 ) => {
  283. res2 = res2.trim();
  284. if ( !res2 ) {
  285. return;
  286. }
  287. const newData = this.data.set( { id: res2 } );
  288. if ( !newData ) {
  289. return;
  290. }
  291. this.treeTable.addNodes( "table-bili-band-config", {
  292. index: 0,
  293. data: newData
  294. } );
  295. this.treeTable.reloadData( "table-bili-band-config" );
  296. };
  297. if ( res ) {
  298. addData( res );
  299. return;
  300. }
  301. layer.prompt( { title: "输入要屏蔽Up主名" }, ( res2, index ) => {
  302. layer.close( index );
  303. addData( res2 );
  304. } );
  305. }
  306. /**
  307. * 删除当前行数据
  308. * @param {Object} e layui数据对象
  309. * */
  310. delete( e ) {
  311. this.data.delete( e.data );
  312. e.del();
  313. this.treeTable.reloadData( "table-bili-band-config" );
  314. }
  315. /** 更新当前行的数据
  316. * @param {Object} originData
  317. * @param {'dynamic' | 'video' | 'live'} type
  318. * @param {number} index
  319. * */
  320. update( originData, type, index ) {
  321. let newData = { ...originData };
  322. switch ( type ) {
  323. case "dynamic":
  324. newData.isBandDynamic = !originData.isBandDynamic;
  325. break;
  326. case "video":
  327. newData.isBandVideo = !originData.isBandVideo;
  328. break;
  329. case "live":
  330. newData.isBandLive = !originData.isBandLive;
  331. break;
  332. }
  333. this.treeTable.updateNode( "table-bili-band-config", index, newData );
  334. this.data.update( newData );
  335. }
  336. /** 改变Up主名称(因为需要改变键值,所以不能直接更新) */
  337. change( e ) {
  338. this.data.change( e.data, e.oldValue );
  339. this.treeTable.reloadData( "table-bili-band-config" );
  340. }
  341. /** 展示UI界面 */
  342. show() {
  343. if ( !this.domList.main ) {
  344. this.getMainDom();
  345. }
  346. const mainContainer = this.domList.main;
  347. if ( mainContainer.style.display === "none" ) {
  348. mainContainer.style.display = "block";
  349. }
  350. mainContainer.classList.remove( "layui-anim-fadeout", "hide" );
  351. mainContainer.classList.add( "layui-anim-fadein" );
  352. }
  353. /** 隐藏UI界面 */
  354. hide() {
  355. if ( !this.domList.main ) {
  356. this.getMainDom();
  357. }
  358. const mainContainer = this.domList.main;
  359. mainContainer.classList.remove( "layui-anim-fadein" );
  360. mainContainer.classList.add( "layui-anim-fadeout", "hide" );
  361. }
  362. getMainDom() {
  363. this.domList.main = document.querySelector( ".bili-band-config-container" );
  364. }
  365. submitSearch( input ) {
  366. const { value } = input;
  367. if ( !value.trim() ) {
  368. return false;
  369. }
  370. input.value = "";
  371. const newData = [];
  372. let isMatchValue = false;
  373. this.data.mapToArray( this.data.data ).forEach( ( bandData ) => {
  374. if ( bandData.id.match( value ) ) {
  375. isMatchValue = true;
  376. newData.unshift( bandData );
  377. }
  378. else {
  379. newData.push( bandData );
  380. }
  381. } );
  382. if ( !isMatchValue ) {
  383. layer.confirm( `没有搜索到UP [${ value }] ,是否新建UP
  384. (2s后自动关闭窗口)`, {
  385. time: 2e3,
  386. btn: [ "确认", "取消" ]
  387. }, ( index ) => {
  388. layer.close( index );
  389. this.add( value );
  390. } );
  391. return false;
  392. }
  393. this.treeTable.reloadData( "table-bili-band-config", {
  394. data: newData,
  395. page: {
  396. // 将当前页面设置到第一页,避免看不到搜索结果
  397. curr: 1
  398. }
  399. } );
  400. }
  401. }
  402.  
  403. class ConfigUI {
  404. constructor() {
  405. // @ts-ignore
  406. __publicField( this, "data" );
  407. // @ts-ignore
  408. __publicField( this, "uiEvent" );
  409. importLayui();
  410. Sleep.windowLoad().then(
  411. () => {
  412. this.data = new Data();
  413. this.uiEvent = new UiEvent( this.data );
  414. this.createContainer();
  415. this.createElementEvent();
  416. this.show = () => {
  417. this.uiEvent.show();
  418. };
  419. this.hide = () => {
  420. this.uiEvent.hide();
  421. };
  422. }
  423. );
  424. }
  425. /** 创建UI界面框架 */
  426. createContainer() {
  427. const container = createElement( {
  428. tagName: "main",
  429. className: [ "bili-band-config-container", "layui-anim", "hide" ],
  430. innerHTML: `<table class="layui-anim-fadeout" id="ID-table-bili-band-config" lay-filter="show"></table>`
  431. } );
  432. addElementToDocument( container, `.bili-band-config-container {position: fixed; top: 0; left:calc(50% - 355px);background: #ffffff; z-index: 10003; width: 710px;}`, document.body );
  433. }
  434. /**
  435. * 创建UI内容,创建UI事件
  436. * */
  437. createElementEvent() {
  438. layui.use( "table", () => {
  439. const { treeTable, form } = layui;
  440. treeTable.render( {
  441. elem: "#ID-table-bili-band-config",
  442. id: "table-bili-band-config",
  443. cols: [ [
  444. {
  445. field: "index",
  446. title: "编号",
  447. type: "numbers",
  448. width: 60
  449. },
  450. {
  451. field: "id",
  452. title: "UP主",
  453. width: 200,
  454. sort: true,
  455. align: "center",
  456. edit: true
  457. },
  458. {
  459. field: "dynamic",
  460. title: "动态卡片",
  461. width: 110,
  462. sort: true,
  463. align: "center",
  464. templet: ( d ) => `<input type="checkbox" lay-skin="switch" lay-filter="toggleDynamicStatus" ${ d.isBandDynamic ? "checked" : "" }/>`
  465. },
  466. {
  467. field: "video",
  468. title: "视频卡片",
  469. width: 110,
  470. sort: true,
  471. align: "center",
  472. templet: ( d ) => `<input type="checkbox" lay-skin="switch" lay-filter="toggleVideoStatus" ${ d.isBandVideo ? "checked" : "" }/>`
  473. },
  474. {
  475. field: "live",
  476. title: "直播卡片",
  477. width: 110,
  478. sort: true,
  479. align: "center",
  480. templet: ( d ) => `<input type="checkbox" lay-skin="switch" lay-filter="toggleLiveStatus" ${ d.isBandLive ? "checked" : "" }/>`
  481. },
  482. {
  483. field: "delete",
  484. title: "操作",
  485. width: 110,
  486. sort: false,
  487. align: "center",
  488. fixed: "right",
  489. templet: () => `<button type="button" class="layui-btn layui-btn-sm layui-btn-danger layui-btn-radius" lay-event="delete">Delete</button>`
  490. }
  491. ] ],
  492. data: this.data.originData,
  493. size: "lg",
  494. skin: "line",
  495. page: {
  496. layout: [ "prev", "page", "next", "count", "skip" ]
  497. },
  498. // 底部工具栏
  499. pagebar: `
  500. <div>
  501. <button type="button" class="layui-btn layui-btn-sm" lay-event="add"> Add </button>
  502. <button type="button" class="layui-btn layui-btn-sm" lay-event="addFromClipboard"> ReadClipboard </button>
  503. <button type="button" class="layui-btn layui-btn-sm layui-btn-warm" lay-event="close"> Close </button>
  504. </div>
  505. `,
  506. // 顶部工具栏
  507. toolbar: `
  508. <div>
  509. <form class="form-search" style="display: flex;">
  510. <input type="text" class="layui-input" style="width: 200px;" placeholder="输入需要搜索的UP主"/>
  511. <button type="button" lay-submit lay-filter="table-search" class="layui-btn" style="margin-left: 20px;">Search</button>
  512. <button type="button" lay-submit lay-filter="table-clear" class="layui-btn" style="margin-left: 20px;">Clear</button>
  513. </form>
  514. </div>
  515. `,
  516. width: 710,
  517. // 不开启顶部右侧默认工具栏
  518. defaultToolbar: ""
  519. } );
  520. treeTable.on( "tool(show)", ( e ) => {
  521. this.uiEvent.delete( e );
  522. } );
  523. treeTable.on( "edit(show)", ( e ) => {
  524. this.uiEvent.change( e );
  525. } );
  526. class Checkbox {
  527. constructor( input ) {
  528. __publicField( this, "input" );
  529. __publicField( this, "domList" );
  530. this.input = input;
  531. this.domList = {
  532. input: this.input,
  533. tr: this.getTrDom()
  534. };
  535. }
  536. getTrDom() {
  537. var _a, _b, _c;
  538. return ( _c = ( _b = ( _a = this.input ) == null ? void 0 : _a.parentElement ) == null ? void 0 : _b.parentElement ) == null ? void 0 : _c.parentElement;
  539. }
  540. getTableDataIndex() {
  541. return parseInt( this.domList.tr.dataset.index );
  542. }
  543. getTableData( index ) {
  544. index || ( index = this.getTableDataIndex() );
  545. return treeTable.getNodeDataByIndex( "table-bili-band-config", index );
  546. }
  547. }
  548. form.on( "switch(toggleDynamicStatus)", ( e ) => {
  549. const input = new Checkbox( e.elem );
  550. const index = input.getTableDataIndex();
  551. const data = input.getTableData( index );
  552. this.uiEvent.update( data, "dynamic", index );
  553. } );
  554. form.on( "switch(toggleVideoStatus)", ( e ) => {
  555. const input = new Checkbox( e.elem );
  556. const index = input.getTableDataIndex();
  557. const data = input.getTableData( index );
  558. this.uiEvent.update( data, "video", index );
  559. } );
  560. form.on( "switch(toggleLiveStatus)", ( e ) => {
  561. const input = new Checkbox( e.elem );
  562. const index = input.getTableDataIndex();
  563. const data = input.getTableData( index );
  564. this.uiEvent.update( data, "live", index );
  565. } );
  566. treeTable.on( "pagebar(show)", ( e ) => {
  567. const { event } = e;
  568. if ( ![ "add", "close", "addFromClipboard" ].includes( event ) ) {
  569. return;
  570. }
  571. if ( event === "add" ) {
  572. this.uiEvent.add();
  573. return;
  574. }
  575. if ( event === "addFromClipboard" ) {
  576. navigator.clipboard.readText().then(
  577. ( res ) => {
  578. this.uiEvent.add( res );
  579. },
  580. ( err ) => {
  581. layer.msg( err );
  582. }
  583. );
  584. return;
  585. }
  586. if ( event === "close" ) {
  587. this.uiEvent.hide();
  588. return;
  589. }
  590. } );
  591. form.on( "submit(table-search)", ( res ) => {
  592. const input = res.form.querySelector( "input" );
  593. this.uiEvent.submitSearch( input );
  594. return false;
  595. } );
  596. form.on( "submit(table-clear)", ( res ) => {
  597. res.form.querySelector( "input" ).value = "";
  598. return false;
  599. } );
  600. const domList = {
  601. form: document.querySelector( ".form-search" ),
  602. input: document.querySelector( ".form-search > input" )
  603. };
  604. domList.form.addEventListener( "submit", ( e ) => {
  605. e.preventDefault();
  606. this.uiEvent.submitSearch( domList.input );
  607. } );
  608. } );
  609. }
  610. // 向外暴露出show事件
  611. // 初始化声明show函数,具体内容会在构造函数定义
  612. show() {
  613. }
  614. // 向外暴露出hide事件
  615. // 初始化声明hide函数,具体内容会在构造函数定义
  616. hide() {
  617. }
  618. }
  619.  
  620. ( async () => {
  621. const print = new Info( "BiliBiliHideDynamic" );
  622. addStyle( `.hide {display: none !important}` );
  623. print.info( "引入UI" );
  624. const configUI = new ConfigUI();
  625. await Sleep.windowLoad();
  626. class Observer {
  627. constructor() {
  628. }
  629. async observe( observerSelectorList, callback ) {
  630. await getElement( document.body, observerSelectorList.waitLoadElementSelector );
  631. const observer2 = new MutationObserver( ( e ) => {
  632. e.forEach( ( record ) => {
  633. var _a;
  634. const item = record.addedNodes[0];
  635. if ( !item || !( ( _a = item == null ? void 0 : item.classList ) == null ? void 0 : _a.contains( observerSelectorList.filterToken || "" ) ) ) {
  636. return;
  637. }
  638. callback( item );
  639. } );
  640. } );
  641. /* @__PURE__ */
  642. ( () => {
  643. } )( observerSelectorList.observeElementSelector );
  644. observer2.observe( document.querySelector( observerSelectorList.observeElementSelector ), {
  645. childList: true
  646. } );
  647. }
  648. }
  649. class BandEvent {
  650. constructor( bandList ) {
  651. __publicField( this, "bandList" );
  652. __publicField( this, "bandTypeList", [ "dynamic", "video" ] );
  653. this.bandList = bandList;
  654. }
  655. /** 判断当前动态的Up主是否在屏蔽列表中,如果是则隐藏 */
  656. band( item, upNameSelector, bandType ) {
  657. var _a;
  658. const upName = ( _a = item.querySelector( upNameSelector ) ) == null ? void 0 : _a.innerText.trim();
  659. let bandTypeKey;
  660. bandTypeKey = {
  661. dynamic: "isBandDynamic",
  662. video: "isBandVideo",
  663. live: "isBandLive"
  664. };
  665. if ( this.bandList.has( upName ) && this.bandList.get( upName )[bandTypeKey[bandType]] ) {
  666. item.classList.add( "hide" );
  667. }
  668. else {
  669. item.classList.remove( "hide" );
  670. }
  671. }
  672. /**
  673. * 获取当前所处的动态卡片编号,并根据动态卡片编号,返回不同的BandType
  674. * */
  675. judgeBandType( tabsItemListSelector ) {
  676. let tabsItemIndex = 0;
  677. const tabsItemList = document.querySelectorAll( tabsItemListSelector );
  678. for ( let i = 0; i < tabsItemList.length; i++ ) {
  679. const tabsItem = tabsItemList[i];
  680. if ( tabsItem.classList.contains( "active" ) ) {
  681. tabsItemIndex = i;
  682. break;
  683. }
  684. }
  685. return this.bandTypeList[tabsItemIndex];
  686. }
  687. /** 刷新页面数据 */
  688. fresh( observerSelectorList, bandType ) {
  689. const { aimElementSelector, upNameSelector } = observerSelectorList;
  690. const upNameNodeList = document.querySelectorAll( aimElementSelector );
  691. upNameNodeList.forEach( ( aimElement ) => {
  692. this.band( aimElement, upNameSelector, bandType );
  693. } );
  694. }
  695. // 刷新动态卡片 / 视频卡片数据
  696. freshDynamic( dynamicSelectorList ) {
  697. const bandType = this.judgeBandType( dynamicSelectorList.tabsItemListSelector );
  698. bandEvent.fresh( dynamicSelectorList, bandType );
  699. }
  700. // 刷新直播数据
  701. freshLive( liveSelectorList ) {
  702. bandEvent.fresh( liveSelectorList, "live" );
  703. }
  704. }
  705. let domSelector = {
  706. dynamic: {
  707. waitLoadElementSelector: ".bili-dyn-list",
  708. observeElementSelector: ".bili-dyn-list__items",
  709. upNameSelector: ".bili-dyn-title__text",
  710. tabsItemListSelector: ".bili-dyn-list-tabs__item",
  711. filterToken: "bili-dyn-list__item",
  712. aimElementSelector: ".bili-dyn-list__item"
  713. },
  714. // Bilibili-Evolved直播侧边栏
  715. live: {
  716. waitLoadElementSelector: ".be-live-list-content",
  717. observeElementSelector: ".be-live-list-content",
  718. upNameSelector: ".be-live-list-item-user",
  719. filterToken: "be-live-list-item",
  720. aimElementSelector: ".be-live-list-item"
  721. },
  722. // 旧版直播侧边栏
  723. oldLive: {
  724. waitLoadElementSelector: ".bili-dyn-live-users__body",
  725. observeElementSelector: ".bili-dyn-live-users__body",
  726. upNameSelector: ".bili-dyn-live-users__item__uname",
  727. filterToken: "bili-dyn-live-users__item",
  728. aimElementSelector: ".bili-dyn-live-users__item"
  729. },
  730. // 新版直播侧边栏
  731. newLive: {
  732. waitLoadElementSelector: ".bili-dyn-live-users__body",
  733. observeElementSelector: ".bili-dyn-live-users__body",
  734. upNameSelector: ".bili-dyn-live-users__item__uname",
  735. filterToken: "bili-dyn-live-users__container",
  736. aimElementSelector: ".bili-dyn-live-users__container"
  737. }
  738. };
  739. ( function judgeBiliUiVersion() {
  740. if ( document.querySelector( "#bili-header-container" ) && document.querySelector( ".bili-header.fixed-header" ) ) {
  741. domSelector.live = domSelector.newLive;
  742. }
  743. else if ( document.querySelector( "#bili-header-container" ) ) {
  744. ;
  745. }
  746. else {
  747. domSelector.live = domSelector.oldLive;
  748. }
  749. } )();
  750. const observer = new Observer();
  751. const bandEvent = new BandEvent( configUI.data.data );
  752. await observer.observe( domSelector.dynamic, ( item ) => {
  753. const bandType = bandEvent.judgeBandType( domSelector.dynamic.tabsItemListSelector );
  754. bandEvent.band( item, domSelector.dynamic.upNameSelector, bandType );
  755. } );
  756. bandEvent.freshDynamic( domSelector.dynamic );
  757. await observer.observe( domSelector.live, ( item ) => {
  758. bandEvent.band( item, domSelector.live.upNameSelector, "live" );
  759. } );
  760. bandEvent.freshLive( domSelector.live );
  761. registerMenu( "添加屏蔽", () => {
  762. configUI.show();
  763. } );
  764. class DragEvent {
  765. constructor() {
  766. // Dom集合
  767. __publicField( this, "domList" );
  768. // 坐标集合
  769. __publicField( this, "position" );
  770. this.domList = {
  771. main: document.querySelector( ".bili-band-config-container" )
  772. };
  773. this.domList.tool = this.domList.main.querySelector( ".layui-table-tool" );
  774. this.position = {
  775. start: { x: 0, y: 0 },
  776. end: { x: 0, y: 0 },
  777. relative: { x: 0, y: 0 }
  778. };
  779. this.bindDragEvent( this.domList.tool );
  780. }
  781. /** 绑定拖拽事件 */
  782. bindDragEvent( willDraggableElement ) {
  783. willDraggableElement.draggable = true;
  784. willDraggableElement.addEventListener( "dragstart", ( e ) => {
  785. this.getStartPosition( e );
  786. } );
  787. willDraggableElement.addEventListener( "dragend", ( e ) => {
  788. e.preventDefault();
  789. this.getEndPosition( e );
  790. this.getRelativePosition();
  791. this.changeDomPosition();
  792. } );
  793. }
  794. /** 获取开始坐标 */
  795. getStartPosition( e ) {
  796. const { pageX, pageY } = e;
  797. this.position.start = {
  798. x: pageX,
  799. y: pageY
  800. };
  801. }
  802. /** 获取结束坐标 */
  803. getEndPosition( e ) {
  804. const { pageX, pageY } = e;
  805. this.position.end = {
  806. x: pageX,
  807. y: pageY
  808. };
  809. }
  810. /** 获取相对坐标 */
  811. getRelativePosition() {
  812. this.position.relative = {
  813. x: this.position.relative.x + this.position.end.x - this.position.start.x,
  814. y: this.position.relative.y + this.position.end.y - this.position.start.y
  815. };
  816. }
  817. /** 改变main容器的坐标位置 */
  818. changeDomPosition() {
  819. this.domList.main.style.transform = `translate(${ this.position.relative.x }px, ${ this.position.relative.y }px)`;
  820. }
  821. }
  822. ( () => {
  823. const domList = {
  824. closeBtn: document.querySelector( "[lay-event=close]" )
  825. };
  826. domList.closeBtn.addEventListener( "click", () => {
  827. bandEvent.freshDynamic( domSelector.dynamic );
  828. bandEvent.freshLive( domSelector.live );
  829. } );
  830. new DragEvent();
  831. } )();
  832. } )();