记录视频刷新历史(bilibili)

记录每次刷新的视频, 可以方便的回溯之前错过的视频

  1. // ==UserScript==
  2. // @name 记录视频刷新历史(bilibili)
  3. // @namespace https://gf.qytechs.cn/zh-CN/users/1196880-ling2ling4
  4. // @version 1.1.8
  5. // @author Ling2Ling4
  6. // @description 记录每次刷新的视频, 可以方便的回溯之前错过的视频
  7. // @license MIT
  8. // @icon data:image/png;base64,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
  9. // @match *://www.bilibili.com/
  10. // @match *://www.bilibili.com/?*
  11. // @match *://www.bilibili.com/index.html
  12. // @run-at document-end
  13. // @grant GM_setValue
  14. // @grant GM_getValue
  15. // @grant GM_registerMenuCommand
  16. // @noframes
  17. // @compatible chrome
  18. // @compatible edge
  19. // @compatible firefox
  20. // ==/UserScript==
  21.  
  22. (() => {
  23. "use strict";
  24. const info = {
  25. hoverColor: "#e3e5e7",
  26. hasCurVideos: !1,
  27. classList: {
  28. vBox: ["container", "no-banner-container", "is-version8"],
  29. video: "feed-card",
  30. addVideo: "add-video",
  31. btnBox: "feed-roll-btn",
  32. btn: "roll-btn",
  33. },
  34. txt: { lBtnTt: "返回上一组视频", rBtnTt: "切换下一组视频" },
  35. saveData: {
  36. histVideos: {
  37. key: "setting_histVideos",
  38. value: [],
  39. base: [],
  40. valType: "array",
  41. },
  42. },
  43. settings: {
  44. isLoadVideo: {
  45. value: !0,
  46. base: !0,
  47. key: "setting_isLoadVideo",
  48. txt: "每次打开B站首页时是否恢复上次关闭的页面的视频历史记录",
  49. type: "基础设置",
  50. valType: "boolean",
  51. compType: "radio",
  52. valueText: {
  53. true: "每次都加载旧的视频历史",
  54. false: "仅记录当前页面的视频历史",
  55. },
  56. },
  57. maxHistory: {
  58. value: 10,
  59. base: 10,
  60. key: "setting_maxHistory",
  61. txt: "设置历史视频的记录页数 (一般一页是10个视频)",
  62. type: "基础设置",
  63. valType: "number",
  64. compType: "textarea",
  65. compH: "30px",
  66. },
  67. histBtnSize: {
  68. value: 20,
  69. base: 20,
  70. key: "setting_histBtnSize",
  71. txt: "设置按钮尺寸 (单位: 像素)",
  72. type: "基础设置",
  73. valType: "number",
  74. compType: "textarea",
  75. compH: "30px",
  76. },
  77. },
  78. settingsArea: null,
  79. };
  80. function getValue({
  81. base,
  82. key,
  83. valType = "string",
  84. isReSet = !0,
  85. getValue = null,
  86. setValue = null,
  87. getVal = null,
  88. setVal = null,
  89. } = {}) {
  90. getValue && (getVal = getValue), setValue && (setVal = setValue);
  91. let val = getVal ? getVal(key) : localStorage.getItem(key);
  92. return (
  93. void 0 !== base &&
  94. null == val &&
  95. ((val = base),
  96. isReSet &&
  97. ("string" != typeof base && (base = JSON.stringify(base)),
  98. setVal ? setVal(key, base) : localStorage.setItem(key, base))),
  99. (valType = valType.toLowerCase()),
  100. "string" == typeof val
  101. ? "string" === valType
  102. ? val
  103. : "boolean" === valType || "number" === valType
  104. ? JSON.parse(val)
  105. : "object" === valType
  106. ? val
  107. ? JSON.parse(val)
  108. : {}
  109. : "array" === valType
  110. ? val
  111. ? JSON.parse(val)
  112. : []
  113. : val
  114. : val
  115. );
  116. }
  117. function getData() {
  118. const settings = info.settings;
  119. for (const valName in settings) {
  120. const setting = settings[valName];
  121. setting.value = getValue({
  122. base: setting.base,
  123. key: setting.key,
  124. valType: setting.valType,
  125. getVal: GM_getValue,
  126. setVal: GM_setValue,
  127. });
  128. }
  129. const saveData = info.saveData;
  130. for (const valName in saveData) {
  131. if ("histVideos" === valName && !settings.isLoadVideo.value) break;
  132. const setting = saveData[valName];
  133. setting.value = getValue({
  134. base: setting.base,
  135. key: setting.key,
  136. valType: setting.valType,
  137. getVal: GM_getValue,
  138. setVal: GM_setValue,
  139. });
  140. }
  141. return info.settings;
  142. }
  143. info.keyBase = "setting_";
  144. const baseCfg = {
  145. state: "",
  146. isEditing: !1,
  147. hasSelectedPage: !1,
  148. param: {
  149. id: "ll_edit_wrap",
  150. box: document.body,
  151. classBase: "ll_edit_",
  152. w: "500px",
  153. h: "",
  154. contentH: "450px",
  155. bg: "rgba(0, 0, 0, 0.15)",
  156. color: "#333",
  157. fontSize: "15px",
  158. fontFamily:
  159. "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif",
  160. zIndex: 11e3,
  161. resetTt: "重置当前页的所有设置为默认值",
  162. isShowMenu: !1,
  163. isScrollStyle: !0,
  164. isResetBtn: !0,
  165. isOnlyResetCurPage: !0,
  166. showPage: void 0,
  167. isIntervalRun: !1,
  168. interval: 1e3,
  169. page: [],
  170. callback: {
  171. resetBefore: null,
  172. reset: null,
  173. confirmBefore: null,
  174. finished: null,
  175. interval: null,
  176. cancelBefore: null,
  177. cancelled: null,
  178. },
  179. },
  180. },
  181. cfg = {
  182. version: "v1.2.2",
  183. isEditing: baseCfg.isEditing,
  184. hasSelectedPage: baseCfg.hasSelectedPage,
  185. timer: null,
  186. interval: 1e3,
  187. param: {},
  188. tempParam: {},
  189. allData: {},
  190. oldData: {},
  191. lastData: {},
  192. baseData: {},
  193. controls: {},
  194. doms: { page: [] },
  195. editText: {},
  196. };
  197. const css = function getCss() {
  198. const param = cfg.param,
  199. cBase = (param.page, param.classBase),
  200. baseStart = `#${param.id} .${cBase}`,
  201. fSize = param.fontSize ? param.fontSize : "14px",
  202. css = `#${
  203. param.id
  204. } {\n position: fixed;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n z-index: ${
  205. param.zIndex || 11e3
  206. };\n background: ${
  207. param.bg || "rgba(0, 0, 0, 0.12)"
  208. };\n display: none;\n}\n${baseStart}box {\n text-align: initial;\n letter-spacing: 1px;\n position: relative;\n width: ${
  209. param.w || "450px"
  210. };\n ${
  211. param.h ? "max-height:" + param.h : ""
  212. };\n margin: auto;\n color: ${
  213. param.color || "#333"
  214. };\n background: #fff;\n font-size: ${fSize};\n line-height: normal;\n font-family: ${
  215. param.fontFamily ||
  216. "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif"
  217. };\n border: 3px solid #dfedfe;\n border-radius: 10px;\n box-sizing: border-box;\n padding: 14px 8px 10px 15px;\n overflow: hidden;\n overflow-y: auto;\n}\n${baseStart}menu {\n font-weight: bold;\n font-size: ${
  218. parseInt(fSize) + 1
  219. }px;\n display: flex;\n flex-wrap: wrap;\n gap: 0 8px;\n}\n${baseStart}menu-item {\n margin-bottom: 8px;\n border: 1px solid #dfedfe;\n color: #9ecaff;\n background: #eef6ff;\n border-radius: 6px;\n padding: 6px 10px;\n cursor: pointer;\n}\n${baseStart}menu-item:hover {\n color: #65aaff;\n background: #dfedfe;\n border: 1px solid #dfedfe;\n}\n${baseStart}menu-item.active {\n color: #65aaff;\n background: #dfedfe;\n border: 1px solid #dfedfe;\n}\n${baseStart}page-box {\n max-height: ${
  220. param.contentH || ""
  221. };\n padding-right: 7px;\n margin-bottom: 8px;\n overflow: hidden;\n overflow-y: auto;\n}\n${baseStart}page {\n display: none;\n}\n${baseStart}page.curPage {\n display: block;\n}\n${baseStart}comp {\n margin-bottom: 8px;\n}\n${baseStart}comp:last-child {\n margin-bottom: 2px;\n}\n${baseStart}tt {\n font-weight: bold;\n font-size: ${
  222. parseInt(fSize) + 6
  223. }px;\n margin-top: 4px;\n}\n${baseStart}tt2 {\n font-weight: bold;\n font-size: ${
  224. parseInt(fSize) + 4
  225. }px;\n margin-top: 3px;\n margin-bottom: 7px;\n}\n${baseStart}tt3 {\n font-weight: bold;\n font-size: ${
  226. parseInt(fSize) + 2
  227. }px;\n margin-top: 2px;\n margin-bottom: 6px;\n}\n${baseStart}desc {\n line-height: 1.5;\n}\n${baseStart}comp-tt {\n font-weight: bold;\n font-size: ${
  228. parseInt(fSize) + 1
  229. }px;\n line-height: 1.5;\n}\n${baseStart}comp-desc {\n line-height: 1.5;\n}\n${baseStart}rd-arr {\n line-height: 22px;\n}\n${baseStart}rd-arr label {\n margin-right: 6px;\n cursor: pointer;\n}\n${baseStart}rd-arr input {\n vertical-align: -2px;\n cursor: pointer;\n}\n${baseStart}rd-arr span {\n color: #666;\n margin-left: 2px;\n}\n#${
  230. param.id
  231. } textarea {\n width: 100%;\n max-width: 100%;\n max-height: 300px;\n border-radius: 6px;\n line-height: normal;\n padding: 5px 7px;\n outline-color: #cee4ff;\n border: 1px solid #aaa;\n box-sizing: border-box;\n font-size: ${
  232. parseInt(fSize) - 2
  233. }px;\n font-family: PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif;\n /* 保留空格 */\n white-space: pre-wrap;\n /* 允许词内换行 */\n word-break: break-all;\n letter-spacing: 1px;\n overflow: hidden;\n overflow-y: auto;\n}\n#${
  234. param.id
  235. } textarea::placeholder {\n color: #bbb;\n}\n${baseStart}ta-desc {\n margin-bottom: 3px;\n}\n${baseStart}btn-box {\n display: flex;\n justify-content: flex-end;\n}\n${baseStart}btn-box button {\n font-size: 16px;\n line-height: normal;\n color: #65aaff;\n background: #dfedfe;\n outline: none;\n border: none;\n border-radius: 6px;\n padding: 8px 16px;\n box-sizing: border-box;\n cursor: pointer;\n}\n${baseStart}btn-box .${cBase}reset-btn {\n position: absolute;\n left: 15px;\n bottom: 10px;\n color: #888;\n background: #f4f4f4;\n margin-right: 15px;\n}\n${baseStart}btn-box .${cBase}reset-btn:hover {\n color: #666;\n background: #eee;\n}\n${baseStart}btn-box .${cBase}cancel-btn {\n color: #888;\n background: #f4f4f4;\n margin-right: 15px;\n}\n${baseStart}btn-box .${cBase}cancel-btn:hover {\n color: #666;\n background: #eee;\n}\n${baseStart}btn-box .${cBase}confirm-btn {\n margin-right: 7px;\n}\n${baseStart}btn-box .${cBase}confirm-btn:hover {\n background: #cee4ff;\n}\n`;
  236. return param.isScrollStyle
  237. ? css +
  238. "\n.ll-scroll-style-1::-webkit-scrollbar,\n.ll-scroll-style-1 ::-webkit-scrollbar {\n width: 8px;\n}\n.ll-scroll-style-1-size-2::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-2::-webkit-scrollbar {\n width: 10px;\n}\n.ll-scroll-style-1-size-3::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-3::-webkit-scrollbar {\n width: 12px;\n}\n.ll-scroll-style-1::-webkit-scrollbar-thumb,\n.ll-scroll-style-1 ::-webkit-scrollbar-thumb {\n border-radius: 10px;\n -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.05);\n opacity: 0.2;\n background: #daedff;\n}\n.ll-scroll-style-1::-webkit-scrollbar-track,\n.ll-scroll-style-1 ::-webkit-scrollbar-track {\n -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.08);\n border-radius: 0;\n background: #fff;\n border-radius: 5px;\n}"
  239. : css;
  240. };
  241. const editArea_html = function getHTML() {
  242. function getCompHTML({ info, active = "", id }) {
  243. let type = info.type;
  244. if (
  245. ((type = {
  246. menuTitle: "mtt",
  247. title: "tt",
  248. title2: "tt2",
  249. title3: "tt3",
  250. desc: "ds",
  251. radio: "rd",
  252. checkbox: "cb",
  253. textarea: "ta",
  254. mtt: "mtt",
  255. tt: "tt",
  256. tt2: "tt2",
  257. tt3: "tt3",
  258. ds: "ds",
  259. rd: "rd",
  260. cb: "cb",
  261. ta: "ta",
  262. }[type]),
  263. (id = 0 === id ? "0" : id || ""),
  264. 0 === info.value && (info.value = "0"),
  265. !type)
  266. )
  267. return console.log("不存在的组件类型"), !1;
  268. let title = "",
  269. desc = "",
  270. ctrlTt = "";
  271. switch (
  272. (["tt", "tt2", "tt3", "ds", "mtt"].includes(type) ||
  273. ((title = info.title
  274. ? `<div class="${cBase}comp-tt ${cBase}${type}-tt" title="${
  275. info.tt || ""
  276. }">${info.title}</div>`
  277. : ""),
  278. (desc = info.desc
  279. ? `<div class="${cBase}comp-desc ${cBase}${type}-desc">${info.desc}</div>`
  280. : "")),
  281. type)
  282. ) {
  283. case "mtt":
  284. return (
  285. (info.value = info.value || ""),
  286. info.value
  287. ? `<div class="${cBase}menu-item ${active || ""}" title="${
  288. info.tt || ""
  289. }">${info.value}</div>`
  290. : ""
  291. );
  292. case "tt":
  293. case "tt2":
  294. case "tt3":
  295. return (
  296. (info.value = info.value || ""),
  297. info.value
  298. ? `<div class="${cBase}${type} ${cBase}comp" title="${
  299. info.tt || ""
  300. }">${info.value}</div>`
  301. : ""
  302. );
  303. case "ds":
  304. return (
  305. (info.value = info.value || ""),
  306. info.value
  307. ? `<div class="${cBase}desc ${cBase}comp" title="${
  308. info.descTt || ""
  309. }">${info.value}</div>`
  310. : ""
  311. );
  312. case "rd":
  313. const name = info.name || info.id + new Date().getTime();
  314. (ctrlTt = info.ctrlTt || ""),
  315. ctrlTt && (ctrlTt = `title="${ctrlTt}"`);
  316. let radio = `<div class="${cBase}rd ${cBase}rd-arr" ${ctrlTt}>`;
  317. if (void 0 === info.value && info.radioList[0]) {
  318. const obj = info.radioList[0];
  319. info.value = void 0 === obj.value ? obj.text : obj.value;
  320. }
  321. return (
  322. info.radioList.forEach((item, i) => {
  323. void 0 === item.value && (info.radioList[i].value = item.text),
  324. void 0 === item.text && (info.radioList[i].text = item.value);
  325. const value = item.value;
  326. let tt = item.tt || "";
  327. tt && (tt = `title="${tt}"`);
  328. let selected = "";
  329. info.value + "" == item.value + "" && (selected = "checked"),
  330. (radio += `<label ${tt}><input ${selected} type="radio" name="${name}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
  331. }),
  332. (radio += "</div>"),
  333. `<div class="${cBase}comp ${cBase}ctrl ${cBase}rd-box" data-type="${type}" data-cpid="${id}">${title}${desc}${radio}</div>`
  334. );
  335. case "cb":
  336. const name2 = info.name || new Date().getTime();
  337. if (
  338. ((ctrlTt = info.ctrlTt || ""),
  339. ctrlTt && (ctrlTt = `title="${ctrlTt}"`),
  340. void 0 === info.value && info.radioList[0])
  341. ) {
  342. const obj = info.radioList[0];
  343. info.value = void 0 === obj.value ? obj.text : obj.value;
  344. }
  345. let checkbox = `<div class="${cBase}cb ${cBase}rd-arr" ${ctrlTt}>`;
  346. return (
  347. info.radioList.forEach((item, i) => {
  348. void 0 === item.value && (info.radioList[i].value = item.text),
  349. void 0 === item.text && (info.radioList[i].text = item.value);
  350. const value = item.value;
  351. let tt = item.tt || "";
  352. tt && (tt = `title="${tt}"`);
  353. let selected = "";
  354. info.value.includes(value) && (selected = "checked"),
  355. (checkbox += `<label ${tt}><input ${selected} type="checkbox" name="${name2}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
  356. }),
  357. (checkbox += "</div>"),
  358. `<div class="${cBase}comp ${cBase}ctrl ${cBase}cb-box" data-type="${type}" data-cpid="${id}">${title}${desc}${checkbox}</div>`
  359. );
  360. case "ta":
  361. const taH = `height:${info.height || "30px"};`,
  362. style = `style="${
  363. info.width ? "width:" + info.width + ";" : ""
  364. }${taH}${
  365. info.fontSize ? "font-size:" + info.fontSize + ";" : ""
  366. }${
  367. info.fontFamily ? "font-family:" + info.fontFamily + ";" : ""
  368. }"`,
  369. textarea = `<textarea class="${cBase}ta" ${style} data-cpid="${id}" placeholder="${
  370. info.ph || ""
  371. }" title="${info.ctrlTt || "拖动右下角可调节宽高"}"></textarea>`;
  372. return `<div class="${cBase}comp ${cBase}ctrl ${cBase}ta-box" data-type="${type}" data-cpid="${id}">${title}${desc}${textarea}</div>`;
  373. }
  374. }
  375. const param = cfg.param,
  376. page = param.page,
  377. cBase = param.classBase,
  378. isMenu = 1 !== page.length;
  379. let menu = `<div class="${cBase}menu">`,
  380. pageHTML = `<div class="${cBase}page-box ll-scroll-style-1 ll-scroll-style-1-size-2">`;
  381. page.forEach((curPage, index) => {
  382. let pgid = curPage.id || index;
  383. (pgid += ""), (cfg.allData[pgid] = {}), (cfg.baseData[pgid] = {});
  384. let pageFlag = "";
  385. if (
  386. (cfg.hasSelectedPage ||
  387. ((void 0 === param.showPage || pgid === param.showPage + "") &&
  388. ((pageFlag = "curPage"), (cfg.hasSelectedPage = !0))),
  389. (pageHTML += `<div class="${cBase}page ${pageFlag}" data-pgid="${pgid}">`),
  390. curPage.components)
  391. ) {
  392. let compIndex = 0;
  393. if (isMenu || param.isShowMenu) {
  394. let curMenu = curPage.components.find(
  395. (item) => "menuTitle" === item.type
  396. );
  397. curMenu || (curMenu = { type: "menuTitle", value: pgid }),
  398. (menu += getCompHTML({
  399. info: curMenu,
  400. active: pageFlag ? "active" : "",
  401. }));
  402. }
  403. curPage.components.forEach((item) => {
  404. const cpid = item.id || compIndex;
  405. "menuTitle" !== item.type &&
  406. (pageHTML += getCompHTML({ info: item, id: cpid })),
  407. ["title", "title2", "title3", "desc", "menuTitle"].includes(
  408. item.type
  409. ) ||
  410. ((item.base = void 0 === item.base ? item.value : item.base),
  411. (cfg.allData[pgid][cpid] = item.value),
  412. (cfg.baseData[pgid][cpid] = item.base),
  413. compIndex++);
  414. });
  415. }
  416. pageHTML += "</div>";
  417. }),
  418. (pageHTML += "</div>"),
  419. isMenu || param.isShowMenu ? (menu += "</div>") : (menu = "");
  420. const resetBtn = param.isResetBtn
  421. ? `<button class="${cBase}reset-btn" title="${
  422. param.resetTt || "重置所有设置为默认值"
  423. }">重置</button>`
  424. : "",
  425. btnBox = `<div class="${cBase}btn-box">\n${resetBtn}\n<button class="${cBase}cancel-btn">取 消</button>\n<button class="${cBase}confirm-btn">确 认</button>\n</div>`;
  426. return `<div class="${cBase}box ll-scroll-style-1 ll-scroll-style-1-size-3" data-version="${cfg.version}">\n${menu}\n${pageHTML}\n${btnBox}\n</div>`;
  427. },
  428. baseParam = baseCfg.param,
  429. controls = cfg.controls,
  430. doms = cfg.doms;
  431. function createEditEle({
  432. id = baseParam.id,
  433. box = baseParam.box,
  434. classBase = baseParam.classBase,
  435. w = baseParam.w,
  436. h = baseParam.h,
  437. contentH = baseParam.contentH,
  438. bg = baseParam.bg,
  439. color = baseParam.color,
  440. fontSize = baseParam.fontSize,
  441. fontFamily = baseParam.fontFamily,
  442. zIndex = baseParam.zIndex,
  443. resetTt = baseParam.resetTt,
  444. isShowMenu = baseParam.isShowMenu,
  445. isScrollStyle = baseParam.isScrollStyle,
  446. isResetBtn = baseParam.isResetBtn,
  447. isOnlyResetCurPage = baseParam.isOnlyResetCurPage,
  448. showPage = baseParam.showPage,
  449. isIntervalRun = baseParam.isIntervalRun,
  450. interval = baseParam.interval,
  451. page = [],
  452. callback = baseParam.callback,
  453. } = {}) {
  454. (cfg.state = baseCfg.state),
  455. (cfg.isEditing = baseCfg.isEditing),
  456. (cfg.hasSelectedPage = baseCfg.hasSelectedPage),
  457. (cfg.param = { ...baseParam });
  458. const param = cfg.param;
  459. (box = box || document.body),
  460. (param.id = id),
  461. (param.box = box),
  462. (param.classBase = classBase),
  463. (param.w = w),
  464. (param.h = h),
  465. (param.contentH = contentH),
  466. (param.bg = bg),
  467. (param.color = color),
  468. (param.fontSize = fontSize),
  469. (param.fontFamily = fontFamily),
  470. (param.zIndex = zIndex),
  471. (param.resetTt = resetTt),
  472. (param.isShowMenu = isShowMenu),
  473. (param.isScrollStyle = isScrollStyle),
  474. (param.isResetBtn = isResetBtn),
  475. (param.isOnlyResetCurPage = isOnlyResetCurPage),
  476. (param.showPage = showPage),
  477. (param.isIntervalRun = isIntervalRun),
  478. (param.interval = interval),
  479. (param.page = page),
  480. (param.callback = callback),
  481. (cfg.interval = interval),
  482. (cfg.callback = callback);
  483. const html = editArea_html();
  484. return (
  485. box.querySelector(`#${param.classBase}${param.id}-css`) ||
  486. (function addCss(cssText, box = document.body, id = "") {
  487. const style = document.createElement("style");
  488. return (
  489. id && (style.id = id),
  490. box.appendChild(style),
  491. (style.innerHTML = cssText),
  492. style
  493. );
  494. })(css(), box, param.classBase + param.id + "-css"),
  495. (doms.wrap = (function createEle({
  496. className = "",
  497. id = "",
  498. title = "",
  499. css,
  500. box = document.body,
  501. type = "div",
  502. } = {}) {
  503. const ele = document.createElement(type);
  504. return (
  505. id && (ele.id = id),
  506. className && (ele.className = className),
  507. title && (ele.title = title),
  508. css && (ele.style.cssText = css),
  509. box.appendChild(ele),
  510. ele
  511. );
  512. })({ className: id, id })),
  513. (doms.wrap.innerHTML = html),
  514. (function getDoms() {
  515. const param = cfg.param,
  516. cBase = param.classBase;
  517. (doms.box = doms.wrap.querySelector(`.${cBase}box`)),
  518. (doms.cancel = doms.box.querySelector(`.${cBase}cancel-btn`)),
  519. (doms.confirm = doms.box.querySelector(`.${cBase}confirm-btn`));
  520. const isMenu = 1 !== param.page.length;
  521. (isMenu || param.isShowMenu) &&
  522. ((doms.menu = doms.box.querySelector(`.${cBase}menu`)),
  523. (doms.menus = [].slice.call(
  524. doms.menu.querySelectorAll(`.${cBase}menu-item`)
  525. )));
  526. const pages = [].slice.call(doms.box.querySelectorAll(`.${cBase}page`));
  527. (doms.page = []),
  528. param.isResetBtn &&
  529. (doms.reset = doms.box.querySelector(`.${cBase}reset-btn`));
  530. pages.forEach((curPage, index) => {
  531. cfg.hasSelectedPage ||
  532. (curPage.classList.add("curPage"),
  533. (isMenu || param.isShowMenu) &&
  534. doms.menus[0].classList.add("active"),
  535. (cfg.hasSelectedPage = !0));
  536. const page = {},
  537. pgid = curPage.dataset.pgid;
  538. (page.pgid = curPage.pgid = pgid),
  539. (page.controls = [].slice.call(
  540. curPage.querySelectorAll(`.${cBase}ctrl`)
  541. )),
  542. (page.ele = curPage),
  543. doms.page.push(page),
  544. (isMenu || param.isShowMenu) &&
  545. (doms.menus[index].settingsPage = curPage);
  546. const ctrls = {};
  547. (controls[pgid] = ctrls),
  548. page.controls.forEach((item, i) => {
  549. const cpid = item.dataset.cpid,
  550. cType = item.dataset.type;
  551. let dom;
  552. (item.cpid = cpid),
  553. "rd" === cType || "cb" === cType
  554. ? ((dom = [].slice.call(item.querySelectorAll("input"))),
  555. (dom.compType = cType))
  556. : "ta" === cType &&
  557. ((dom = item.querySelector("textarea")),
  558. (dom.compType = cType),
  559. (dom.value = cfg.allData[pgid][cpid])),
  560. (ctrls[cpid] = dom);
  561. });
  562. });
  563. })(),
  564. cfg.timer && clearInterval(cfg.timer),
  565. (function bindEvents() {
  566. const param = cfg.param;
  567. function menuHandle(e) {
  568. const dom = e.target,
  569. cBase = param.classBase;
  570. if (dom.classList.contains(`${cBase}menu-item`)) {
  571. const old = doms.menu.querySelector(".active");
  572. old.classList.remove("active"),
  573. old.settingsPage.classList.remove("curPage"),
  574. dom.classList.add("active"),
  575. dom.settingsPage.classList.add("curPage");
  576. }
  577. }
  578. function cancelEdit(e) {
  579. const cBase = param.classBase;
  580. if (
  581. (e.stopPropagation(),
  582. e.target.className !== `${cBase}wrap` &&
  583. e.target.className !== `${cBase}cancel-btn`)
  584. )
  585. return;
  586. const callback = cfg.callback;
  587. !1 !== runCallback(callback.cancelBefore) &&
  588. (showEditArea(!1),
  589. setCompValue(cfg.oldData),
  590. param.isIntervalRun &&
  591. (setCompValue(cfg.oldData), (cfg.allData = cfg.oldData)),
  592. runCallback(callback.cancelled));
  593. }
  594. function confirmEdit() {
  595. const callback = cfg.callback,
  596. data = getAllData();
  597. (cfg.allData = data),
  598. !1 !== runCallback(callback.confirmBefore, data) &&
  599. (showEditArea(!1),
  600. (cfg.state = "finished"),
  601. runCallback(callback.finished, data),
  602. (cfg.state = ""));
  603. }
  604. function resetEdit() {
  605. const callback = cfg.callback,
  606. data = getAllData();
  607. !1 !== runCallback(callback.resetBefore, data) &&
  608. (!(function resetEditData(isOnlyPage = !1) {
  609. const param = cfg.param;
  610. if (param.isResetBtn)
  611. if (isOnlyPage) {
  612. const data = getAllData(),
  613. curMenu = doms.menu.querySelector(".active");
  614. (data[curMenu.innerText] = cfg.baseData[curMenu.innerText]),
  615. setCompValue(data);
  616. } else setCompValue(cfg.baseData);
  617. })(param.isOnlyResetCurPage),
  618. runCallback(callback.reset, data));
  619. }
  620. doms.menu && doms.menu.addEventListener("click", menuHandle),
  621. doms.wrap.addEventListener("click", cancelEdit),
  622. doms.cancel.addEventListener("click", cancelEdit),
  623. doms.confirm.addEventListener("click", confirmEdit),
  624. doms.reset && doms.reset.addEventListener("click", resetEdit);
  625. })(),
  626. (cfg.state = "created"),
  627. cfg
  628. );
  629. }
  630. function getAllData() {
  631. function getCompItem(pgid, cpid) {
  632. if (!controls[pgid]) return;
  633. const ctrl = controls[pgid][cpid];
  634. if (ctrl) {
  635. if (!Array.isArray(ctrl)) return ctrl.value;
  636. if ("rd" === ctrl.compType) {
  637. const result = ctrl.find((item) => item.checked).dataset.val;
  638. return "false" !== result && ("true" === result || result);
  639. }
  640. if ("cb" === ctrl.compType) {
  641. return ctrl
  642. .filter((item) => item.checked)
  643. .map((item) => {
  644. const value = item.dataset.val;
  645. return "false" !== value && ("true" === value || value);
  646. });
  647. }
  648. }
  649. }
  650. const data = {};
  651. if (0 === arguments.length) {
  652. for (const key in controls) {
  653. const page = controls[key];
  654. data[key] = {};
  655. for (const key2 in page) data[key][key2] = getCompItem(key, key2);
  656. }
  657. return data;
  658. }
  659. if (1 === arguments.length) {
  660. const ctrls = arguments[0];
  661. for (const pgid in ctrls) {
  662. data[pgid] = {};
  663. controls[pgid].forEach((cpid) => {
  664. data[pgid][cpid] = getCompItem(pgid, cpid);
  665. });
  666. }
  667. return cfg.allData;
  668. }
  669. return getCompItem(arguments[0], arguments[1]);
  670. }
  671. function setCompValue() {
  672. function setCompItem(pgid, cpid, value) {
  673. if (!controls[pgid]) return;
  674. const ctrl = controls[pgid][cpid];
  675. if (ctrl)
  676. if (Array.isArray(ctrl)) {
  677. if ("rd" === ctrl.compType) {
  678. const selected = ctrl.find((item) => item.checked);
  679. selected && (selected.checked = !1);
  680. const select = ctrl.find((item) => item.dataset.val === value + "");
  681. select && (select.checked = !0);
  682. } else if ("cb" === ctrl.compType) {
  683. if (
  684. (ctrl
  685. .filter((item) => item.checked)
  686. .forEach((item) => {
  687. item.checked = !1;
  688. }),
  689. Array.isArray(value))
  690. )
  691. value.forEach((val) => {
  692. const select = ctrl.find(
  693. (item) => item.dataset.val === val + ""
  694. );
  695. select && (select.checked = !0);
  696. });
  697. else {
  698. const select = ctrl.find(
  699. (item) => item.dataset.val === value + ""
  700. );
  701. select && (select.checked = !0);
  702. }
  703. }
  704. } else ctrl.value = value;
  705. }
  706. if (1 === arguments.length) {
  707. const data = arguments[0];
  708. for (const key in data) {
  709. const pageData = data[key];
  710. for (const key2 in pageData) {
  711. setCompItem(key, key2, pageData[key2]);
  712. }
  713. }
  714. } else {
  715. setCompItem(arguments[0], arguments[1], arguments[2]);
  716. }
  717. }
  718. function showEditArea(isShow = !0, callback = null) {
  719. if (
  720. (cfg.param.isIntervalRun &&
  721. (cfg.timer && clearInterval(cfg.timer),
  722. (cfg.timer = setInterval(() => {
  723. const data = getAllData(),
  724. oldType = cfg.state;
  725. (cfg.state = "interval"),
  726. runCallback(cfg.callback.interval, data),
  727. (cfg.state = oldType),
  728. (cfg.lastData = data);
  729. }, cfg.interval))),
  730. (cfg.state = "created"),
  731. isShow)
  732. ) {
  733. if (((cfg.oldData = getAllData()), "function" == typeof callback)) {
  734. if (!1 === callback(cfg.oldData, cfg.oldData, cfg.baseData)) return;
  735. }
  736. cfg.state = "show";
  737. }
  738. (cfg.isEditing = isShow),
  739. (doms.wrap.style.display = isShow ? "block" : "none"),
  740. isShow &&
  741. !doms.box.style.top &&
  742. (doms.box.style.top =
  743. window.innerHeight / 2 - doms.box.clientHeight / 2 + "px"),
  744. callback && (cfg.callback = callback);
  745. }
  746. function runCallback(callback, data) {
  747. let result;
  748. if (callback) {
  749. data || (data = getAllData());
  750. const func = callback;
  751. Array.isArray(func)
  752. ? func.curFn
  753. ? ((result = func[curFn](data, cfg.oldData, cfg.baseData)),
  754. (func.curFn = null))
  755. : func.forEach((fn) => {
  756. result = fn(data, cfg.oldData, cfg.baseData);
  757. })
  758. : "function" == typeof callback &&
  759. (result = func(data, cfg.oldData, cfg.baseData));
  760. }
  761. return result;
  762. }
  763. function setValue({
  764. value,
  765. base,
  766. key,
  767. verification = null,
  768. getValue = null,
  769. setValue = null,
  770. getVal = null,
  771. setVal = null,
  772. } = {}) {
  773. getValue && (getVal = getValue), setValue && (setVal = setValue);
  774. let f = !1;
  775. try {
  776. (getVal !== GM_getValue && setVal !== GM_setValue) || (f = !0);
  777. } catch (e) {}
  778. let newVal = value,
  779. oldVal = getVal ? getVal(key) : localStorage.getItem(key);
  780. return (
  781. void 0 !== base &&
  782. null == oldVal &&
  783. ((oldVal = base),
  784. "string" == typeof base || f || (base = JSON.stringify(base)),
  785. setVal ? setVal(key, base) : localStorage.setItem(key, base)),
  786. null !== newVal &&
  787. ("function" != typeof verification ||
  788. ((newVal = verification(newVal, oldVal, base)), null !== newVal)) &&
  789. newVal !== oldVal &&
  790. ("string" == typeof newVal || f || (newVal = JSON.stringify(newVal)),
  791. setVal ? setVal(key, newVal) : localStorage.setItem(key, newVal),
  792. !0)
  793. );
  794. }
  795. const settings = info.settings,
  796. videoHist_info = {
  797. maxHistory: null,
  798. isLoadVideo: null,
  799. size: null,
  800. histVideos: null,
  801. hoverColor: info.hoverColor,
  802. loadNum: 0,
  803. index: 0,
  804. hasCurVideos: !1,
  805. },
  806. txt = { lBtnTt: info.txt.lBtnTt, rBtnTt: info.txt.rBtnTt },
  807. classList = info.classList,
  808. videoHist_doms = {};
  809. let vHistory = [];
  810. function updateData() {
  811. (videoHist_info.maxHistory = settings.maxHistory.value),
  812. (videoHist_info.isLoadVideo = settings.isLoadVideo.value),
  813. (videoHist_info.size = parseInt(settings.histBtnSize.value)),
  814. videoHist_info.isLoadVideo &&
  815. ((videoHist_info.histVideos = info.saveData.histVideos.value),
  816. (function loadVideos() {
  817. (vHistory = videoHist_info.histVideos),
  818. vHistory.forEach((vArr) => {
  819. vArr.forEach((item, i, arr) => {
  820. arr[i] = (function strToDom(str) {
  821. let tmpDom = document.createElement("div");
  822. tmpDom.innerHTML = str;
  823. const dom = tmpDom.children[0];
  824. return (tmpDom = null), dom;
  825. })(item);
  826. });
  827. }),
  828. (videoHist_info.index = vHistory.length),
  829. (videoHist_info.hasCurVideos = !1);
  830. })());
  831. }
  832. function getMaxIndex() {
  833. return vHistory.length - 1 + (videoHist_info.hasCurVideos ? 0 : 1);
  834. }
  835. function getVideos() {
  836. let arr;
  837. arr = [].slice.call(
  838. videoHist_doms.vBox.querySelectorAll("." + classList.video)
  839. );
  840. const addVideos = videoHist_doms.vBox.querySelectorAll(
  841. "." + classList.addVideo
  842. );
  843. return (
  844. addVideos.length > 0 && (arr = arr.concat([].slice.call(addVideos))),
  845. (arr = arr.filter((i) => "none" !== i.style.display)),
  846. (videoHist_doms.curVideos = arr),
  847. arr
  848. );
  849. }
  850. function updateHistory() {
  851. if (
  852. ((videoHist_doms.curVideos = getVideos()),
  853. !vHistory[vHistory.length - 1] ||
  854. videoHist_doms.curVideos[0] !== vHistory[vHistory.length - 1][0])
  855. )
  856. return (
  857. vHistory.push(videoHist_doms.curVideos),
  858. videoHist_info.index === vHistory.length - 1 &&
  859. (videoHist_info.hasCurVideos = !0),
  860. vHistory.length > videoHist_info.maxHistory &&
  861. (vHistory.splice(0, 1), videoHist_info.index--),
  862. videoHist_info.isLoadVideo &&
  863. (function saveVideos() {
  864. const arr = [];
  865. vHistory.forEach((vArr) => {
  866. const curArr = [];
  867. vArr.forEach((item) => {
  868. curArr.push(
  869. (function domToString(dom) {
  870. let tmpDom = document.createElement("div");
  871. tmpDom.appendChild(dom.cloneNode(!0));
  872. const str = tmpDom.innerHTML;
  873. return (tmpDom = null), str;
  874. })(item)
  875. );
  876. }),
  877. arr.push(curArr);
  878. }),
  879. setValue({
  880. value: JSON.stringify(arr),
  881. base: "",
  882. key: info.saveData.histVideos.key,
  883. getValue: GM_getValue,
  884. setValue: GM_setValue,
  885. });
  886. })(),
  887. !0
  888. );
  889. }
  890. function historyChange(f = "left") {
  891. if (
  892. (videoHist_info.hasCurVideos ||
  893. videoHist_info.index !== vHistory.length - 1 + 1 ||
  894. updateHistory(),
  895. "right" === f)
  896. ) {
  897. if ((videoHist_info.index++, videoHist_info.index > vHistory.length - 1))
  898. return void (videoHist_info.index = vHistory.length - 1);
  899. } else if ((videoHist_info.index--, videoHist_info.index < 0))
  900. return void (videoHist_info.index = 0);
  901. !(function delCurVideos() {
  902. getVideos().forEach((ele) => {
  903. ele.remove();
  904. });
  905. })();
  906. const twoVideo = videoHist_doms.vBox.children[1];
  907. vHistory[videoHist_info.index].forEach((ele) => {
  908. videoHist_doms.vBox.insertBefore(ele, twoVideo);
  909. });
  910. }
  911. function historyBtns() {
  912. let i = 0;
  913. const timer = setInterval(() => {
  914. i >= 5 && clearInterval(timer),
  915. i++,
  916. (videoHist_doms.btnBox = document.querySelector(
  917. "." + classList.btnBox
  918. )),
  919. (videoHist_doms.btn =
  920. videoHist_doms.btnBox &&
  921. videoHist_doms.btnBox.querySelector("." + classList.btn)),
  922. videoHist_doms.btnBox &&
  923. videoHist_doms.btn &&
  924. (!(function createBtns() {
  925. const dom = document.createElement("div");
  926. (dom.innerHTML = `<div id="vHistory-box" style="display:flex;width:100%;line-height:1.6;margin-top:10px">\n <style>.vHistoryBtn {width:${
  927. videoHist_info.size
  928. }px;height:${
  929. videoHist_info.size
  930. }px;text-align:center;border-radius:${
  931. videoHist_info.size / 5
  932. }px;cursor:pointer;}\n .vHistoryBtn:hover {background:${
  933. videoHist_info.hoverColor
  934. };}</style>\n <div class="left-historyBtn vHistoryBtn" title="${
  935. txt.lBtnTt
  936. }">\n <svg t="1698507568902" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"\n p-id="918" xmlns:xlink="http://www.w3.org/1999/xlink" width="${
  937. videoHist_info.size - 6
  938. }" height="${
  939. videoHist_info.size - 6
  940. }">\n <path d="M796.444444 113.777778c0 17.066667-5.688889 34.133333-17.066666 45.511111L409.6 472.177778c-5.688889 11.377778-11.377778 17.066667-11.377778 34.133333 0 5.688889 5.688889 22.755556 11.377778 28.444445l364.088889 329.955555c22.755556 22.755556 22.755556 56.888889 5.688889 79.644445-22.755556 22.755556-56.888889 22.755556-79.644445 5.688888l-364.088889-329.955555c-34.133333-28.444444-51.2-73.955556-51.2-119.46666699s22.755556-85.333333 56.888889-119.46666601l364.088889-312.888889c22.755556-22.755556 56.888889-17.066667 79.644445 5.688889 5.688889 11.377778 11.377778 28.444444 11.377777 39.822222z" fill="#999999" p-id="919"></path>\n </svg>\n </div>\n <div class="right-historyBtn vHistoryBtn" title="${
  941. txt.rBtnTt
  942. }">\n <svg t="1698507574371" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"\n p-id="1067" xmlns:xlink="http://www.w3.org/1999/xlink" width="${
  943. videoHist_info.size - 6
  944. }" height="${
  945. videoHist_info.size - 6
  946. }">\n <path d="M227.555556 910.222222c0-17.066667 5.688889-34.133333 17.066666-45.511111L614.4 551.822222c5.688889-11.377778 11.377778-17.066667 11.377778-34.133333 0-5.688889-5.688889-22.755556-11.377778-28.444445l-364.088889-329.955555c-22.755556-22.755556-22.755556-56.888889-5.688889-79.644445 22.755556-22.755556 56.888889-22.755556 79.644445-5.688888l364.088889 329.955555c34.133333 28.444444 51.2 73.955556 51.2 119.46666699s-22.755556 85.333333-56.888889 119.46666601l-364.088889 312.888889c-22.755556 22.755556-56.888889 17.066667-79.644445-5.688889-5.688889-11.377778-11.377778-28.444444-11.377777-39.822222z" fill="#999999" p-id="1068"></path>\n </svg>\n </div>\n</div>`),
  947. videoHist_doms.btnBox.appendChild(dom),
  948. (videoHist_doms.lBtn =
  949. videoHist_doms.btnBox.querySelector(".left-historyBtn")),
  950. (videoHist_doms.rBtn =
  951. videoHist_doms.btnBox.querySelector(".right-historyBtn"));
  952. })(),
  953. videoHist_doms.lBtn &&
  954. videoHist_doms.rBtn &&
  955. (!(function videoHist_bindEvents() {
  956. videoHist_doms.btn.addEventListener("click", () => {
  957. videoHist_info.index !== getMaxIndex() &&
  958. (vHistory.splice(
  959. videoHist_info.index + 1,
  960. vHistory.length - 1 - videoHist_info.index
  961. ),
  962. (videoHist_info.index = getMaxIndex()),
  963. (videoHist_info.hasCurVideos = !0)),
  964. videoHist_info.index === getMaxIndex() &&
  965. (videoHist_info.index++,
  966. (videoHist_info.hasCurVideos = !1)),
  967. updateHistory();
  968. }),
  969. videoHist_doms.lBtn.addEventListener("click", () => {
  970. historyChange("left");
  971. }),
  972. videoHist_doms.rBtn.addEventListener("click", () => {
  973. historyChange("right");
  974. }),
  975. window.addEventListener("beforeunload", () => {
  976. videoHist_info.index === getMaxIndex() && updateHistory();
  977. });
  978. })(),
  979. clearInterval(timer)));
  980. }, 1e3);
  981. }
  982. function toPageObj({ settings, param = {}, otherPageName = "无分类" } = {}) {
  983. param = { ...param };
  984. const pageArr = [],
  985. menuList = [];
  986. let isOtherType = !1;
  987. for (let key in settings) {
  988. const item = settings[key];
  989. item.type
  990. ? menuList.includes(item.type) || menuList.push(item.type)
  991. : isOtherType || (isOtherType = !0);
  992. }
  993. return (
  994. isOtherType && menuList.push(otherPageName),
  995. menuList.forEach((menuTt) => {
  996. const components = [],
  997. page = { id: menuTt, components },
  998. arr = [];
  999. for (let key in settings) {
  1000. const item = settings[key];
  1001. menuTt === otherPageName
  1002. ? item.type || arr.push(item)
  1003. : item.type === menuTt && arr.push(item);
  1004. }
  1005. arr.forEach((item) => {
  1006. let desc = item.desc || item.txt || "";
  1007. desc && (desc = desc.replaceAll("\n", "<br>").trim());
  1008. let comp,
  1009. base = item.base;
  1010. if (
  1011. (Array.isArray(base) && (base = base.join(", ")), item.groupTitle1)
  1012. ) {
  1013. const comp = {
  1014. id: item.key + "-gTt1",
  1015. type: "title",
  1016. value: item.groupTitle1,
  1017. };
  1018. components.push(comp);
  1019. }
  1020. if (item.groupTitle2) {
  1021. const comp = {
  1022. id: item.key + "-gTt2",
  1023. type: "title2",
  1024. value: item.groupTitle2,
  1025. };
  1026. components.push(comp);
  1027. }
  1028. if (item.groupTitle3) {
  1029. const comp = {
  1030. id: item.key + "-gTt3",
  1031. type: "title3",
  1032. value: item.groupTitle3,
  1033. };
  1034. components.push(comp);
  1035. }
  1036. if (item.groupDesc) {
  1037. const comp = {
  1038. id: item.key + "-gDesc",
  1039. type: "desc",
  1040. value: item.groupDesc,
  1041. };
  1042. components.push(comp);
  1043. }
  1044. if (
  1045. (["menuTitle", "title", "desc", "title2", "title3"].includes(
  1046. item.compType
  1047. )
  1048. ? ((comp = { ...item }),
  1049. (comp.type = comp.compType),
  1050. (comp.desc = desc))
  1051. : (comp = {
  1052. id: item.key,
  1053. type: item.compType,
  1054. tt: item.tt || "",
  1055. title: item.title || "",
  1056. desc,
  1057. descTt: item.descTt || "",
  1058. name: item.key,
  1059. value: item.value,
  1060. base: item.base,
  1061. }),
  1062. "textarea" === comp.type)
  1063. )
  1064. (comp.ph = base),
  1065. (comp.width = item.compW),
  1066. (comp.height = item.compH),
  1067. (comp.ctrlTt = "默认: " + base);
  1068. else if ("radio" === comp.type || "checkbox" === comp.type) {
  1069. let str = "默认: ";
  1070. if ("checkbox" === comp.type) {
  1071. let arr = item.base;
  1072. Array.isArray(arr) || (arr = arr.split(/,|,/)),
  1073. arr.forEach((val, i) => {
  1074. 0 !== i && (str += ", "), (val = val.trim());
  1075. let valTxt = item.valueText[val];
  1076. void 0 === valTxt && (valTxt = val), (str += valTxt);
  1077. });
  1078. } else {
  1079. let val = item.valueText[item.base];
  1080. void 0 === val && (val = item.base), (str += val);
  1081. }
  1082. comp.ctrlTt = str;
  1083. }
  1084. if (item.valueText) {
  1085. comp.radioList = [];
  1086. for (let key in item.valueText) {
  1087. const rd = { text: item.valueText[key], value: key };
  1088. comp.radioList.push(rd);
  1089. }
  1090. }
  1091. components.push(comp);
  1092. }),
  1093. pageArr.push(page);
  1094. }),
  1095. (param.page = pageArr),
  1096. param
  1097. );
  1098. }
  1099. function showSettings() {
  1100. const settings = info.settings;
  1101. (info.settingsArea = (function createEdit({
  1102. settings,
  1103. param = {},
  1104. oldEditCfg,
  1105. updateDataFn,
  1106. isNewEdit = !0,
  1107. isSyncOtherPage = !0,
  1108. otherPageName = "无分类",
  1109. } = {}) {
  1110. let oldSettings, curSettings;
  1111. updateDataFn &&
  1112. isSyncOtherPage &&
  1113. ((oldSettings = JSON.stringify(settings)),
  1114. (settings = updateDataFn() || settings),
  1115. (curSettings = JSON.stringify(settings)));
  1116. const editInfo = { settings, param, otherPageName };
  1117. if (oldEditCfg) {
  1118. if (isNewEdit)
  1119. return (
  1120. oldEditCfg.doms.wrap.remove(), createEditEle(toPageObj(editInfo))
  1121. );
  1122. isSyncOtherPage &&
  1123. updateDataFn &&
  1124. oldSettings !== curSettings &&
  1125. (oldEditCfg.doms.wrap.remove(),
  1126. (oldEditCfg = createEditEle(toPageObj(editInfo)))),
  1127. isSyncOtherPage &&
  1128. !updateDataFn &&
  1129. (oldEditCfg.doms.wrap.remove(),
  1130. (oldEditCfg = createEditEle(toPageObj(editInfo))));
  1131. } else oldEditCfg = createEditEle(toPageObj(editInfo));
  1132. return oldEditCfg;
  1133. })({
  1134. settings,
  1135. param: { isShowMenu: !0 },
  1136. oldEditCfg: info.settingsArea,
  1137. updateDataFn: getData,
  1138. })),
  1139. updateData();
  1140. showEditArea(!0, {
  1141. resetBefore: () => {},
  1142. confirmBefore: () => {},
  1143. finished: (data) => {
  1144. console.log(data);
  1145. if (
  1146. (function isValueChange(type = "auto") {
  1147. const param = cfg.param,
  1148. curData = getAllData(),
  1149. curDataStr = JSON.stringify(curData);
  1150. let oldDataStr;
  1151. return (
  1152. "auto" === type &&
  1153. ("interval" === cfg.state &&
  1154. param.isIntervalRun &&
  1155. (type = "interval_current"),
  1156. "finished" === cfg.state && (type = "auto")),
  1157. (oldDataStr =
  1158. "interval_current" === type
  1159. ? JSON.stringify(cfg.lastData)
  1160. : "base_current" === type
  1161. ? JSON.stringify(cfg.baseData)
  1162. : JSON.stringify(cfg.oldData)),
  1163. "{}" !== oldDataStr && curDataStr !== oldDataStr
  1164. );
  1165. })()
  1166. ) {
  1167. for (const pageName in data) {
  1168. const page = data[pageName];
  1169. for (const key in page) {
  1170. const value = page[key];
  1171. let verifyFn;
  1172. const flag = key.replace(info.keyBase, ""),
  1173. item = settings[flag];
  1174. switch (key) {
  1175. case settings.isLoadVideo.key:
  1176. break;
  1177. case settings.maxHistory.key:
  1178. verifyFn = (newVal) =>
  1179. (newVal = +newVal) < 1 || !newVal
  1180. ? settings.maxHistory.base
  1181. : newVal;
  1182. break;
  1183. case settings.histBtnSize.key:
  1184. verifyFn = (newVal) =>
  1185. (newVal = parseInt(newVal)) < 10 || !newVal
  1186. ? settings.histBtnSize.base
  1187. : newVal;
  1188. }
  1189. if (!item)
  1190. return void console.log("设置的数据对应的对象获取失败");
  1191. setValue({
  1192. value,
  1193. base: item.base,
  1194. key,
  1195. verification: verifyFn,
  1196. getValue: GM_getValue,
  1197. setValue: GM_setValue,
  1198. });
  1199. }
  1200. }
  1201. history.go(0);
  1202. }
  1203. },
  1204. });
  1205. }
  1206. getData(),
  1207. GM_registerMenuCommand("设置", () => {
  1208. showSettings();
  1209. }),
  1210. (function main() {
  1211. videoHist_info.loadNum++,
  1212. videoHist_info.loadNum > 3
  1213. ? console.log("视频元素的容器元素获取失败")
  1214. : (updateData(),
  1215. (function videoHist_getDoms() {
  1216. if (
  1217. ("string" == typeof classList.vBox
  1218. ? (videoHist_doms.vBox = document.querySelector(
  1219. "." + classList.vBox
  1220. ))
  1221. : classList.vBox.forEach((item) => {
  1222. !videoHist_doms.vBox &&
  1223. (videoHist_doms.vBox = document.querySelector(
  1224. "." + item
  1225. ));
  1226. }),
  1227. !videoHist_doms.vBox)
  1228. ) {
  1229. const dom = document.querySelector("." + classList.video);
  1230. if (
  1231. (dom && (videoHist_doms.vBox = dom.parentElement),
  1232. !videoHist_doms.vBox)
  1233. )
  1234. return;
  1235. }
  1236. })(),
  1237. videoHist_doms.vBox
  1238. ? historyBtns()
  1239. : setTimeout(() => {
  1240. main();
  1241. }, 500));
  1242. })();
  1243. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址