BiliBili动态隐藏

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

目前為 2023-07-23 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name BiliBili动态隐藏
  3. // @author Yiero
  4. // @description 根据Up主名称,在动态页进行筛选,隐藏屏蔽的Up主动态。
  5. // @version 1.4.1
  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. map.set( value.id, value );
  250. } );
  251. return map;
  252. }
  253. /**
  254. * Map转数组
  255. * @param {Map} map
  256. * @return {any[]}
  257. * */
  258. mapToArray( map ) {
  259. const array = [];
  260. for ( let value of map.values() ) {
  261. array.push( value );
  262. }
  263. return array;
  264. }
  265. }
  266.  
  267. class UiEvent {
  268. constructor( data ) {
  269. __publicField( this, "data" );
  270. __publicField( this, "treeTable" );
  271. __publicField( this, "domList" );
  272. this.data = data;
  273. this.treeTable = layui.treeTable;
  274. this.domList = {
  275. main: void 0
  276. };
  277. this.getMainDom();
  278. }
  279. /** 添加数据 */
  280. add() {
  281. layer.prompt( { title: "输入要屏蔽Up主名" }, ( res, index ) => {
  282. layer.close( index );
  283. if ( !res.trim() ) {
  284. return;
  285. }
  286. const newData = this.data.set( { id: res } );
  287. this.treeTable.addNodes( "table-bili-band-config", {
  288. index: 0,
  289. data: newData
  290. } );
  291. this.treeTable.reloadData( "table-bili-band-config" );
  292. } );
  293. }
  294. /**
  295. * 删除当前行数据
  296. * @param {Object} e layui数据对象
  297. * */
  298. delete( e ) {
  299. this.data.delete( e.data );
  300. e.del();
  301. this.treeTable.reloadData( "table-bili-band-config" );
  302. }
  303. /** 更新当前行的数据
  304. * @param {Object} originData
  305. * @param {'dynamic' | 'video' | 'live'} type
  306. * @param {number} index
  307. * */
  308. update( originData, type, index ) {
  309. let newData = { ...originData };
  310. switch ( type ) {
  311. case "dynamic":
  312. newData.isBandDynamic = !originData.isBandDynamic;
  313. break;
  314. case "video":
  315. newData.isBandVideo = !originData.isBandVideo;
  316. break;
  317. case "live":
  318. newData.isBandLive = !originData.isBandLive;
  319. break;
  320. }
  321. this.treeTable.updateNode( "table-bili-band-config", index, newData );
  322. this.data.update( newData );
  323. }
  324. /** 改变Up主名称(因为需要改变键值,所以不能直接更新) */
  325. change( e ) {
  326. this.data.change( e.data, e.oldValue );
  327. this.treeTable.reloadData( "table-bili-band-config" );
  328. }
  329. /** 展示UI界面 */
  330. show() {
  331. if ( !this.domList.main ) {
  332. this.getMainDom();
  333. }
  334. const mainContainer = this.domList.main;
  335. if ( mainContainer.style.display === "none" ) {
  336. mainContainer.style.display = "block";
  337. }
  338. mainContainer.classList.remove( "layui-anim-fadeout", "hide" );
  339. mainContainer.classList.add( "layui-anim-fadein" );
  340. }
  341. /** 隐藏UI界面 */
  342. hide() {
  343. if ( !this.domList.main ) {
  344. this.getMainDom();
  345. }
  346. const mainContainer = this.domList.main;
  347. mainContainer.classList.remove( "layui-anim-fadein" );
  348. mainContainer.classList.add( "layui-anim-fadeout", "hide" );
  349. }
  350. getMainDom() {
  351. this.domList.main = document.querySelector( ".bili-band-config-container" );
  352. }
  353. }
  354.  
  355. class ConfigUI {
  356. constructor() {
  357. // @ts-ignore
  358. __publicField( this, "data" );
  359. // @ts-ignore
  360. __publicField( this, "uiEvent" );
  361. importLayui();
  362. Sleep.windowLoad().then(
  363. () => {
  364. this.data = new Data();
  365. this.uiEvent = new UiEvent( this.data );
  366. this.createContainer();
  367. this.createElementEvent();
  368. this.show = () => {
  369. this.uiEvent.show();
  370. };
  371. this.hide = () => {
  372. this.uiEvent.hide();
  373. };
  374. }
  375. );
  376. }
  377. /** 创建UI界面框架 */
  378. createContainer() {
  379. const container = createElement( {
  380. tagName: "main",
  381. className: [ "bili-band-config-container", "layui-anim", "hide" ],
  382. innerHTML: `<table class="layui-anim-fadeout" id="ID-table-bili-band-config" lay-filter="show"></table>`
  383. } );
  384. addElementToDocument( container, `.bili-band-config-container {position: fixed; top: 0; left:calc(50% - 355px);background: #ffffff; z-index: 10003; width: 710px;}`, document.body );
  385. }
  386. /**
  387. * 创建UI内容,创建UI事件
  388. * */
  389. createElementEvent() {
  390. layui.use( "table", () => {
  391. const { treeTable, form } = layui;
  392. treeTable.render( {
  393. elem: "#ID-table-bili-band-config",
  394. id: "table-bili-band-config",
  395. cols: [ [
  396. {
  397. field: "index",
  398. title: "编号",
  399. type: "numbers",
  400. width: 60
  401. },
  402. {
  403. field: "id",
  404. title: "UP主",
  405. width: 200,
  406. sort: true,
  407. align: "center",
  408. edit: true
  409. },
  410. {
  411. field: "dynamic",
  412. title: "动态卡片",
  413. width: 110,
  414. sort: true,
  415. align: "center",
  416. templet: ( d ) => `<input type="checkbox" lay-skin="switch" lay-filter="toggleDynamicStatus" ${ d.isBandDynamic ? "checked" : "" }/>`
  417. },
  418. {
  419. field: "video",
  420. title: "视频卡片",
  421. width: 110,
  422. sort: true,
  423. align: "center",
  424. templet: ( d ) => `<input type="checkbox" lay-skin="switch" lay-filter="toggleVideoStatus" ${ d.isBandVideo ? "checked" : "" }/>`
  425. },
  426. {
  427. field: "live",
  428. title: "直播卡片",
  429. width: 110,
  430. sort: true,
  431. align: "center",
  432. templet: ( d ) => `<input type="checkbox" lay-skin="switch" lay-filter="toggleLiveStatus" ${ d.isBandLive ? "checked" : "" }/>`
  433. },
  434. {
  435. field: "delete",
  436. title: "操作",
  437. width: 110,
  438. sort: false,
  439. align: "center",
  440. fixed: "right",
  441. templet: () => `<button type="button" class="layui-btn layui-btn-sm layui-btn-danger layui-btn-radius" lay-event="delete">Delete</button>`
  442. }
  443. ] ],
  444. data: this.data.originData,
  445. size: "lg",
  446. skin: "line",
  447. page: {
  448. layout: [ "prev", "page", "next", "count", "skip" ]
  449. },
  450. pagebar: `
  451. <div>
  452. <button type="button" class="layui-btn layui-btn-sm" lay-event="add">
  453. Add
  454. </button>
  455. <button type="button" class="layui-btn layui-btn-sm layui-btn-warm" lay-event="close">
  456. Close
  457. </button>
  458. </div>
  459. `,
  460. toolbar: `
  461. <div>
  462. <form style="display: flex;">
  463. <input type="text" class="layui-input" style="width: 200px;" placeholder="输入需要搜索的UP主"/>
  464. <button type="button" lay-submit lay-filter="table-search" class="layui-btn" style="margin-left: 20px;">Search</button>
  465. <button type="button" lay-submit lay-filter="table-clear" class="layui-btn" style="margin-left: 20px;">Clear</button>
  466. </form>
  467. </div>
  468. `,
  469. width: 710,
  470. defaultToolbar: ""
  471. } );
  472. treeTable.on( "tool(show)", ( e ) => {
  473. this.uiEvent.delete( e );
  474. } );
  475. treeTable.on( "edit(show)", ( e ) => {
  476. this.uiEvent.change( e );
  477. } );
  478. class Checkbox {
  479. constructor( input ) {
  480. __publicField( this, "input" );
  481. __publicField( this, "domList" );
  482. this.input = input;
  483. this.domList = {
  484. input: this.input,
  485. tr: this.getTrDom()
  486. };
  487. }
  488. getTrDom() {
  489. var _a, _b, _c;
  490. return ( _c = ( _b = ( _a = this.input ) == null ? void 0 : _a.parentElement ) == null ? void 0 : _b.parentElement ) == null ? void 0 : _c.parentElement;
  491. }
  492. getTableDataIndex() {
  493. return parseInt( this.domList.tr.dataset.index );
  494. }
  495. getTableData( index ) {
  496. index || ( index = this.getTableDataIndex() );
  497. return treeTable.getNodeDataByIndex( "table-bili-band-config", index );
  498. }
  499. }
  500. form.on( "switch(toggleDynamicStatus)", ( e ) => {
  501. const input = new Checkbox( e.elem );
  502. const index = input.getTableDataIndex();
  503. const data = input.getTableData( index );
  504. this.uiEvent.update( data, "dynamic", index );
  505. } );
  506. form.on( "switch(toggleVideoStatus)", ( e ) => {
  507. const input = new Checkbox( e.elem );
  508. const index = input.getTableDataIndex();
  509. const data = input.getTableData( index );
  510. this.uiEvent.update( data, "video", index );
  511. } );
  512. form.on( "switch(toggleLiveStatus)", ( e ) => {
  513. const input = new Checkbox( e.elem );
  514. const index = input.getTableDataIndex();
  515. const data = input.getTableData( index );
  516. this.uiEvent.update( data, "live", index );
  517. } );
  518. treeTable.on( "pagebar(show)", ( e ) => {
  519. const { event } = e;
  520. if ( [ "add", "close" ].indexOf( event ) === -1 ) {
  521. return;
  522. }
  523. if ( event === "add" ) {
  524. this.uiEvent.add();
  525. return;
  526. }
  527. if ( event === "close" ) {
  528. this.uiEvent.hide();
  529. }
  530. } );
  531. form.on( "submit(table-search)", ( res ) => {
  532. const input = res.form.querySelector( "input" );
  533. const { value } = input;
  534. if ( !value.trim() ) {
  535. return;
  536. }
  537. const newData = [];
  538. this.data.mapToArray( this.data.data ).forEach( ( bandData ) => {
  539. if ( bandData.id.match( value ) ) {
  540. newData.unshift( bandData );
  541. }
  542. else {
  543. newData.push( bandData );
  544. }
  545. } );
  546. treeTable.reloadData( "table-bili-band-config", {
  547. data: newData
  548. } );
  549. input.value = "";
  550. return false;
  551. } );
  552. form.on( "submit(table-clear)", ( res ) => {
  553. res.form.querySelector( "input" ).value = "";
  554. return false;
  555. } );
  556. } );
  557. }
  558. // 向外暴露出show事件
  559. // 初始化声明show函数,具体内容会在构造函数定义
  560. show() {
  561. }
  562. // 向外暴露出hide事件
  563. // 初始化声明hide函数,具体内容会在构造函数定义
  564. hide() {
  565. }
  566. }
  567.  
  568. ( async () => {
  569. const print = new Info( "BiliBiliHideDynamic" );
  570. addStyle( `.hide {display: none !important}` );
  571. print.info( "引入UI" );
  572. const configUI = new ConfigUI();
  573. await Sleep.windowLoad();
  574. /* @__PURE__ */
  575. ( () => {
  576. } )( configUI.data );
  577. class Observer {
  578. constructor() {
  579. }
  580. async observe( observerSelectorList, callback ) {
  581. await getElement( document.body, observerSelectorList.waitLoadElementSelector );
  582. const observer2 = new MutationObserver( ( e ) => {
  583. e.forEach( ( record ) => {
  584. var _a;
  585. const item = record.addedNodes[0];
  586. if ( !item || !( ( _a = item == null ? void 0 : item.classList ) == null ? void 0 : _a.contains( observerSelectorList.filterToken || "" ) ) ) {
  587. return;
  588. }
  589. callback( item );
  590. } );
  591. } );
  592. /* @__PURE__ */
  593. ( () => {
  594. } )( observerSelectorList.observeElementSelector );
  595. observer2.observe( document.querySelector( observerSelectorList.observeElementSelector ), {
  596. childList: true
  597. } );
  598. }
  599. }
  600. class BandEvent {
  601. constructor( bandList ) {
  602. __publicField( this, "bandList" );
  603. __publicField( this, "bandTypeList", [ "dynamic", "video" ] );
  604. this.bandList = bandList;
  605. }
  606. /** 判断当前动态的Up主是否在屏蔽列表中,如果是则隐藏 */
  607. band( item, upNameSelector, bandType ) {
  608. var _a;
  609. const upName = ( _a = item.querySelector( upNameSelector ) ) == null ? void 0 : _a.innerText.trim();
  610. let bandTypeKey;
  611. bandTypeKey = {
  612. dynamic: "isBandDynamic",
  613. video: "isBandVideo",
  614. live: "isBandLive"
  615. };
  616. if ( this.bandList.has( upName ) && this.bandList.get( upName )[bandTypeKey[bandType]] ) {
  617. item.classList.add( "hide" );
  618. }
  619. else {
  620. item.classList.remove( "hide" );
  621. }
  622. }
  623. /**
  624. * 获取当前所处的动态卡片编号,并根据动态卡片编号,返回不同的BandType
  625. * */
  626. judgeBandType( tabsItemListSelector ) {
  627. let tabsItemIndex = 0;
  628. const tabsItemList = document.querySelectorAll( tabsItemListSelector );
  629. for ( let i = 0; i < tabsItemList.length; i++ ) {
  630. const tabsItem = tabsItemList[i];
  631. if ( tabsItem.classList.contains( "active" ) ) {
  632. tabsItemIndex = i;
  633. break;
  634. }
  635. }
  636. return this.bandTypeList[tabsItemIndex];
  637. }
  638. /** 刷新页面数据 */
  639. fresh( observerSelectorList, bandType ) {
  640. const { aimElementSelector, upNameSelector } = observerSelectorList;
  641. const upNameNodeList = document.querySelectorAll( aimElementSelector );
  642. upNameNodeList.forEach( ( aimElement ) => {
  643. this.band( aimElement, upNameSelector, bandType );
  644. } );
  645. }
  646. // 刷新动态卡片 / 视频卡片数据
  647. freshDynamic( dynamicSelectorList ) {
  648. const bandType = this.judgeBandType( dynamicSelectorList.tabsItemListSelector );
  649. bandEvent.fresh( dynamicSelectorList, bandType );
  650. }
  651. // 刷新直播数据
  652. freshLive( liveSelectorList ) {
  653. bandEvent.fresh( liveSelectorList, "live" );
  654. }
  655. }
  656. let domSelector = {
  657. dynamic: {
  658. waitLoadElementSelector: ".bili-dyn-list",
  659. observeElementSelector: ".bili-dyn-list__items",
  660. upNameSelector: ".bili-dyn-title__text",
  661. tabsItemListSelector: ".bili-dyn-list-tabs__item",
  662. filterToken: "bili-dyn-list__item",
  663. aimElementSelector: ".bili-dyn-list__item"
  664. },
  665. // Bilibili-Evolved直播侧边栏
  666. live: {
  667. waitLoadElementSelector: ".be-live-list-content",
  668. observeElementSelector: ".be-live-list-content",
  669. upNameSelector: ".be-live-list-item-user",
  670. filterToken: "be-live-list-item",
  671. aimElementSelector: ".be-live-list-item"
  672. },
  673. // 旧版直播侧边栏
  674. oldLive: {
  675. waitLoadElementSelector: ".bili-dyn-live-users__body",
  676. observeElementSelector: ".bili-dyn-live-users__body",
  677. upNameSelector: ".bili-dyn-live-users__item__uname",
  678. filterToken: "bili-dyn-live-users__item",
  679. aimElementSelector: ".bili-dyn-live-users__item"
  680. },
  681. // 新版直播侧边栏
  682. newLive: {
  683. waitLoadElementSelector: ".bili-dyn-live-users__body",
  684. observeElementSelector: ".bili-dyn-live-users__body",
  685. upNameSelector: ".bili-dyn-live-users__item__uname",
  686. filterToken: "bili-dyn-live-users__container",
  687. aimElementSelector: ".bili-dyn-live-users__container"
  688. }
  689. };
  690. ( function judgeBiliUiVersion() {
  691. if ( document.querySelector( "#bili-header-container" ) && document.querySelector( ".bili-header.fixed-header" ) ) {
  692. domSelector.live = domSelector.newLive;
  693. }
  694. else if ( document.querySelector( "#bili-header-container" ) ) {
  695. ;
  696. }
  697. else {
  698. domSelector.live = domSelector.oldLive;
  699. }
  700. } )();
  701. const observer = new Observer();
  702. const bandEvent = new BandEvent( configUI.data.data );
  703. await observer.observe( domSelector.dynamic, ( item ) => {
  704. const bandType = bandEvent.judgeBandType( domSelector.dynamic.tabsItemListSelector );
  705. bandEvent.band( item, domSelector.dynamic.upNameSelector, bandType );
  706. } );
  707. bandEvent.freshDynamic( domSelector.dynamic );
  708. await observer.observe( domSelector.live, ( item ) => {
  709. bandEvent.band( item, domSelector.live.upNameSelector, "live" );
  710. } );
  711. bandEvent.freshLive( domSelector.live );
  712. registerMenu( "添加屏蔽", () => {
  713. configUI.show();
  714. } );
  715. class DragEvent {
  716. constructor() {
  717. // Dom集合
  718. __publicField( this, "domList" );
  719. // 坐标集合
  720. __publicField( this, "position" );
  721. this.domList = {
  722. main: document.querySelector( ".bili-band-config-container" )
  723. };
  724. this.domList.tool = this.domList.main.querySelector( ".layui-table-tool" );
  725. this.position = {
  726. start: { x: 0, y: 0 },
  727. end: { x: 0, y: 0 },
  728. relative: { x: 0, y: 0 }
  729. };
  730. this.bindDragEvent( this.domList.tool );
  731. }
  732. /** 绑定拖拽事件 */
  733. bindDragEvent( willDraggableElement ) {
  734. willDraggableElement.draggable = true;
  735. willDraggableElement.addEventListener( "dragstart", ( e ) => {
  736. this.getStartPosition( e );
  737. } );
  738. willDraggableElement.addEventListener( "dragend", ( e ) => {
  739. e.preventDefault();
  740. this.getEndPosition( e );
  741. this.getRelativePosition();
  742. this.changeDomPosition();
  743. } );
  744. }
  745. /** 获取开始坐标 */
  746. getStartPosition( e ) {
  747. const { pageX, pageY } = e;
  748. this.position.start = {
  749. x: pageX,
  750. y: pageY
  751. };
  752. }
  753. /** 获取结束坐标 */
  754. getEndPosition( e ) {
  755. const { pageX, pageY } = e;
  756. this.position.end = {
  757. x: pageX,
  758. y: pageY
  759. };
  760. }
  761. /** 获取相对坐标 */
  762. getRelativePosition() {
  763. this.position.relative = {
  764. x: this.position.relative.x + this.position.end.x - this.position.start.x,
  765. y: this.position.relative.y + this.position.end.y - this.position.start.y
  766. };
  767. }
  768. /** 改变main容器的坐标位置 */
  769. changeDomPosition() {
  770. this.domList.main.style.transform = `translate(${ this.position.relative.x }px, ${ this.position.relative.y }px)`;
  771. }
  772. }
  773. ( () => {
  774. const domList = {
  775. closeBtn: document.querySelector( "[lay-event=close]" )
  776. };
  777. domList.closeBtn.addEventListener( "click", () => {
  778. bandEvent.freshDynamic( domSelector.dynamic );
  779. bandEvent.freshLive( domSelector.live );
  780. } );
  781. new DragEvent();
  782. } )();
  783. } )();