settings

轻小说文库++的脚本设置界面

当前为 2022-09-16 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/450210/1094328/settings.js

  1. /* eslint-disable no-multi-spaces */
  2. /* eslint-disable no-implicit-globals */
  3. /* eslint-disable userscripts/no-invalid-headers */
  4. /* eslint-disable userscripts/no-invalid-grant */
  5.  
  6. // ==UserScript==
  7. // @name settings
  8. // @displayname 设置界面
  9. // @namespace Wenku8++
  10. // @version 0.2
  11. // @description 轻小说文库++的脚本设置界面
  12. // @author PY-DNG
  13. // @license GPL-v3
  14. // @regurl https?://www\.wenku8\.net/.*
  15. // @require https://greasyfork.org/scripts/449412-basic-functions/code/Basic%20Functions.js?version=1085783
  16. // @require https://greasyfork.org/scripts/449583-configmanager/code/ConfigManager.js?version=1085836
  17. // @grant GM_getValue
  18. // @grant GM_setValue
  19. // @grant GM_deleteValue
  20. // @grant GM_listValues
  21. // @grant ML_listModules
  22. // @grant ML_disableModule
  23. // @grant ML_enableModule
  24. // @grant ML_uninstallModule
  25. // @grant ML_moduleLoaded
  26. // @protect
  27. // ==/UserScript==
  28.  
  29. /*
  30. 计划任务:
  31. [ ] 模块列表排序显示
  32. [-] 不可用按钮灰选
  33. [ ] 模块详细信息展示
  34. [ ] 模块运行状态展示
  35. */
  36.  
  37. (function __MAIN__() {
  38. const ASSETS = require('assets');
  39. const alertify = require('alertify');
  40. const tippy = require('tippy');
  41. const SPanel = require('SidePanel');
  42. const SettingPanel = require('SettingPanel');
  43. const mousetip = require('mousetip');
  44. const CONST = {
  45. Text: {
  46. Button: '设置',
  47. Title: '脚本设置',
  48. ModuleManage: '模块管理',
  49. OpenModuleDialog: '点此打开管理面板',
  50. ModuleSettings: '模块设置',
  51. Module: '模块',
  52. Operation: '操作',
  53. DisableModule: '禁用模块',
  54. EnableModule: '启用模块',
  55. NotDisablable: '不可禁用',
  56. UninstallModule: '卸载模块',
  57. NotUninstallable: '不可卸载',
  58. AlertTitle: '模块设置界面',
  59. NoLoadNoSettings: '模块并未在此页面上运行,无法获取设置',
  60. NoSettings: '该模块当前并没有提供设置选项',
  61. },
  62. Faicon: {
  63. Info: 'fa-regular fa-circle-info'
  64. },
  65. Config_Ruleset: {
  66. 'version-key': 'config-version',
  67. 'ignores': ["LOCAL-CDN"],
  68. 'defaultValues': {
  69. //'config-key': {},
  70. },
  71. 'updaters': {
  72. /*'config-key': [
  73. function() {
  74. // This function contains updater for config['config-key'] from v0 to v1
  75. },
  76. function() {
  77. // This function contains updater for config['config-key'] from v1 to v2
  78. }
  79. ]*/
  80. }
  81. }
  82. };
  83.  
  84. const UMManager = new UserModuleManager();
  85. SPanel.add({
  86. faicon: 'fa-solid fa-gear',
  87. tip: CONST.Text.Button,
  88. onclick: UMManager.show
  89. });
  90.  
  91. exports = {
  92. isSettingPage: isSettingPage,
  93. insertLines: insertLines,
  94. registerSettings: UMManager.registerModuleSettings
  95. };
  96.  
  97. function main() {
  98. // Get elements
  99. const content = $('#content');
  100.  
  101. // Insert settings
  102. const title = [
  103. [{html: CONST.Text.Title, colSpan: 3, class: 'foot', key: 'settitle'}],
  104. [{html: CONST.Text.ModuleManage, colSpan: 1}, {html: CONST.Text.OpenModuleDialog, colSpan: 2, onclick: UMManager.show}],
  105. //[{html: CONST.Text.XXXX, colSpan: 1, key: 'xxxxxxxx'}, {html: CONST.Text.XXXX, colSpan: 2, key: 'xxxxxxxx'}],
  106. ]
  107. const elements = insertLines(title);
  108.  
  109. // scrollIntoView if need
  110. getUrlArgv('tosettings') === 'true' && elements.settitle.scrollIntoView();
  111. }
  112.  
  113. // Module manager user interface
  114. function UserModuleManager() {
  115. const UMM = this;
  116. const moduleSettingFuncs = {};
  117.  
  118. UMM.show = show;
  119.  
  120. UMM.registerModuleSettings = registerModuleSettings;
  121.  
  122. UMM.showModuleSettings = showModuleSettings;
  123.  
  124. function show() {
  125. //box.set('message', 'No implemented yet!').show();
  126. const modules = ML_listModules();
  127.  
  128. // Make panel
  129. const SetPanel = new SettingPanel.SettingPanel({
  130. header: CONST.Text.ModuleManage,
  131. tables: []
  132. });
  133.  
  134. // Make table
  135. const table = new SetPanel.PanelTable({});
  136.  
  137. // Make header
  138. table.appendRow({
  139. blocks: [{
  140. isHeader: true,
  141. colSpan: 1,
  142. width: '60%',
  143. innerText: CONST.Text.Module,
  144. },{
  145. isHeader: true,
  146. colSpan: 4,
  147. width: '40%',
  148. innerText: CONST.Text.Operation,
  149. }]
  150. });
  151.  
  152. // Make module rows
  153. for (const module of modules) {
  154. const row = new SetPanel.PanelRow({
  155. blocks: [{
  156. colSpan: 1,
  157. rowSpan: 1,
  158. children: [
  159. (() => {
  160. const icon = $CrE('i');
  161. icon.className = CONST.Faicon.Info;
  162. icon.style.marginRight = '0.5em';
  163. tippy(icon, module.description);
  164. return icon;
  165. }) (),
  166. (() => {
  167. const span = $CrE('span');
  168. span.innerText = module.displayname || module.name;
  169. return span;
  170. }) (),
  171. ],
  172. },{
  173. colSpan: 1,
  174. rowSpan: 1,
  175. children: [makeBtn(
  176. CONST.Text.ModuleSettings,
  177. showModuleSettings.bind(null, module.identifier)
  178. )]
  179. },{
  180. colSpan: 1,
  181. rowSpan: 1,
  182. children: [makeBtn(
  183. canDisable(module) ? CONST.Text.DisableModule : CONST.Text.NotDisablable,
  184. canDisable(module) ? ML_disableModule.bind(null, module.identifier) : null,
  185. canDisable(module)
  186. )]
  187. },{
  188. colSpan: 1,
  189. rowSpan: 1,
  190. children: [makeBtn(
  191. CONST.Text.EnableModule,
  192. ML_enableModule.bind(null, module.identifier)
  193. )]
  194. },{
  195. colSpan: 1,
  196. rowSpan: 1,
  197. children: [makeBtn(
  198. canUninstall(module) ? CONST.Text.UninstallModule : CONST.Text.NotUninstallable,
  199. canUninstall(module) ? ML_uninstallModule.bind(null, module.identifier) : null,
  200. canUninstall(module)
  201. )]
  202. }]
  203. });
  204. table.appendRow(row);
  205. }
  206. SetPanel.appendTable(table);
  207.  
  208. function makeBtn(text, onclick, disabled) {
  209. const span = $CrE('span');
  210. span.innerText = text;
  211. onclick && span.addEventListener('click', onclick);
  212. span.classList.add(disabled ? ASSETS.ClassName.Disabled : ASSETS.ClassName.Button);
  213. return span;
  214. }
  215.  
  216. function canUninstall(module) {
  217. return !(module.flags & ASSETS.FLAG.NO_UNINSTALL);
  218. }
  219.  
  220. function canDisable(module) {
  221. return !(module.flags & ASSETS.FLAG.NO_DISABLE);
  222. }
  223. }
  224.  
  225. function registerModuleSettings(id, func) {
  226. moduleSettingFuncs[id] = func;
  227. }
  228.  
  229. function showModuleSettings(id) {
  230. const func = moduleSettingFuncs[id];
  231. if (typeof func === 'function') {
  232. func();
  233. return true;
  234. } else {
  235. if (!ML_moduleLoaded(id)) {
  236. alertify.alert(CONST.Text.AlertTitle, CONST.Text.NoLoadNoSettings);
  237. } else {
  238. alertify.alert(CONST.Text.AlertTitle, CONST.Text.NoSettings);
  239. }
  240. return false;
  241. }
  242. }
  243. }
  244.  
  245. function insertLines(lines, tbody) {
  246. !tbody && (tbody = $(content, 'table>tbody'));
  247. const elements = {};
  248. for (const line of lines) {
  249. const tr = $CrE('tr');
  250. for (const item of line) {
  251. const td = $CrE('td');
  252. item.html && (td.innerHTML = item.html);
  253. item.colSpan && (td.colSpan = item.colSpan);
  254. item.class && (td.className = item.class);
  255. item.id && (td.id = item.id);
  256. item.tiptitle && mousetip.settip(td, item.tiptitle);
  257. item.key && (elements[item.key] = td);
  258. if (item.onclick) {
  259. td.style.color = 'grey';
  260. td.style.textAlign = 'center';
  261. td.addEventListener('click', item.onclick);
  262. }
  263. td.style.padding = '3px';
  264. tr.appendChild(td);
  265. }
  266. tbody.appendChild(tr);
  267. }
  268. return elements;
  269. }
  270.  
  271. function isSettingPage(callback) {
  272. const page = getAPI()[0] === 'userdetail.php';
  273. page && callback && callback();
  274. return page;
  275. }
  276.  
  277. function htmlEncode(text) {
  278. const span = $CrE('div');
  279. span.innerText = text;
  280. return span.innerHTML;
  281. }
  282.  
  283. // Change location.href without reloading using history.pushState/replaceState
  284. function setPageUrl() {
  285. let win, url, push;
  286. switch (arguments.length) {
  287. case 1:
  288. win = window;
  289. url = arguments[0];
  290. push = false;
  291. break;
  292. case 2:
  293. win = arguments[0];
  294. url = arguments[1];
  295. push = false;
  296. break;
  297. case 3:
  298. win = arguments[0];
  299. url = arguments[1];
  300. push = arguments[2];
  301. }
  302. return win.history[push ? 'pushState' : 'replaceState']({modified: true, ...history.state}, '', url);
  303. }
  304. })();