commit
						5e7b5d1f40
					
				
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						| @ -1 +1 @@ | ||||
| {"armeabi-v7a":"a36bb21eec579e2c4bed0009eb0f1587","x86":"afce9bdd790c215374bb906919179ca5","arm64-v8a":"3ea9fa21d9b18860cfa12957c39dded1","x86_64":"717c1ebe0d1d3562f5c91c2b2606d2c2","version":"104.0.5112.69"} | ||||
| {"arm64-v8a":"11ded68691faa98fb1ab552210c8d4a8","armeabi-v7a":"4a986b523de502fc85ba6ea51f6f7184","x86_64":"80a642112fe079f3d689a6420a27e926","x86":"e72bf103350222d212bcb0b641733d43","version":"105.0.5195.77"} | ||||
| @ -1,5 +1,5 @@ | ||||
| { | ||||
|   "uploadUrl": "http://sy.mgz6.cc/shuyuan,{\"method\":\"POST\",\"body\": {\"file\": \"fileRequest\"},\"type\": \"multipart/form-data\"}", | ||||
|   "downloadUrlRule": "$.data@js:if (result == '') \n '' \n else \n 'http://shuyuan.mgz6.cc/shuyuan/' + result", | ||||
|   "downloadUrlRule": "$.data@js:if (result == '') \n '' \n else \n 'https://shuyuan.mgz6.cc/shuyuan/' + result", | ||||
|   "summary": "有效期2天" | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| @font-face{font-family:Cascadia;src:url(../fonts/Cascadia-Code-Regular-2.97c09831.ttf)}.editor{display:flex;align-items:stretch;height:100vh}.left{width:calc(50% - 55px);min-width:500px;display:inline-block}.main{width:100%;height:calc(100vh - 64px);overflow-y:auto}textarea{min-height:20px;flex:1;outline:none;border-radius:4px;border:1px solid #ccc;font-size:14px;font-family:Cascadia,Microsoft YaHei UI,Arial,serif;line-height:20px;padding:10px 10px 10px}.fixed[data-v-ab8a8a34]{position:fixed;top:100px;left:50%;transform:translateX(-50%)}.half-circle-spinner [data-v-ab8a8a34],.half-circle-spinner[data-v-ab8a8a34]{box-sizing:border-box}.half-circle-spinner[data-v-ab8a8a34]{width:60px;height:60px;border-radius:100%;position:relative}.half-circle-spinner .circle[data-v-ab8a8a34]{content:"";position:absolute;width:100%;height:100%;border-radius:100%;border:6px solid transparent}.half-circle-spinner .circle.circle-1[data-v-ab8a8a34]{border-top-color:#ff1d5e;-webkit-animation:half-circle-spinner-animation-ab8a8a34 1s infinite;animation:half-circle-spinner-animation-ab8a8a34 1s infinite}.half-circle-spinner .circle.circle-2[data-v-ab8a8a34]{border-bottom-color:#ff1d5e;-webkit-animation:half-circle-spinner-animation-ab8a8a34 1s infinite alternate;animation:half-circle-spinner-animation-ab8a8a34 1s infinite alternate}@-webkit-keyframes half-circle-spinner-animation-ab8a8a34{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes half-circle-spinner-animation-ab8a8a34{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.warm[data-v-27eae50d]{position:fixed;top:100px;left:50%;transform:translateX(-50%);color:#eee;background-color:#ff1d5e;padding:20px;border-radius:8px;font-size:18px}button[data-v-27eae50d]{float:right;width:70px;height:35px;outline:none;border:unset;border-radius:8px;font-size:14px;transition:background-color .3s ease}.success[data-v-bef92f74],button[data-v-27eae50d]:hover{color:#333;background-color:#7fffd4}.success[data-v-bef92f74]{z-index:3;position:fixed;top:100px;left:50%;transform:translateX(-50%);padding:10px;border-radius:8px}p[data-v-bef92f74]{margin:0}.menu{display:flex;flex-direction:column;justify-content:center}button[data-v-8302f478]{width:100px;height:50px;margin:5px;outline:none;padding:10px;font-size:16px;border-radius:4px;box-sizing:border-box;border:1px solid #333;background-color:transparent;transition:all .3s ease;overflow:hidden}button span[data-v-8302f478]{display:inline-block;transform:translateY(20px);opacity:0;font-size:12px;transition:all .3s ease}button[data-v-8302f478]:hover{color:#fff;background-color:gray}button:hover span[data-v-8302f478]{transform:translateY(0);opacity:1}textarea[data-v-4301c68c]{font-size:14px}input[data-v-f11ea0d0]{outline:none;height:25px;font-size:16px}textarea[data-v-f11ea0d0]{font-size:14px}.search[data-v-260cb454]{border:1px solid #ddd;border-radius:4px}input[data-v-260cb454]{text-align:center;font-size:16px;height:25px;outline:none}.tool[data-v-260cb454]{display:flex;justify-content:space-around;padding:4px 0}.tool button[data-v-260cb454]{border-radius:4px;padding:5px;outline:none;border:none;flex:1;margin:0 2px}.tool button[data-v-260cb454]:hover{background-color:#ddd}input[type=checkbox][data-v-260cb454]{transform:scale(2);margin:0 15px 0}.book_item[data-v-260cb454]{overflow:hidden;display:flex;align-items:center;margin-top:10px;padding:10px;cursor:pointer;background-color:#eee}.book_active[data-v-260cb454]{background-color:#32cd32}.book_index[data-v-260cb454]{width:auto;height:30px;text-align:center;line-height:30px;border-radius:8px;padding:0 10px;background-color:#ffb6c1}.book_info[data-v-260cb454]{display:flex;justify-content:space-between}.book_list[data-v-260cb454]{height:calc(100vh - 125px);overflow-y:auto}a[data-v-c4c82b2c]{display:block;height:25px;transition:margin-left .3s ease}a[data-v-c4c82b2c]:hover{color:red;margin-left:10px}code[data-v-c4c82b2c]{display:inline-block;font-size:16px;font-family:Cascadia Mono,JetBrains Mono,Microsoft YaHei UI,serif;background-color:#f3f4f4;border-radius:4px}.author[data-v-c4c82b2c]{position:fixed;right:20px;bottom:20px}.author a[data-v-c4c82b2c]{padding:5px 10px;border-radius:4px}.author a[data-v-c4c82b2c]:hover{box-shadow:0 0 3px 3px #ccc;background-color:#ddd}.out{min-width:620px}.out,.out .box{flex:1;display:flex;flex-flow:column}a{text-decoration:none;color:#333}body,ul{margin:0;padding:0}ul{width:100%;height:40px;display:flex}ul li{display:block;text-align:center;line-height:40px;width:16%;list-style:none;cursor:pointer}ul li:hover{color:red}.active{color:#fff!important;background-color:hsla(0,0%,50%,.459);border-bottom:unset!important}ul li[data-v-de4729c0]{border-bottom:2px solid #333}a[data-v-de4729c0]{font-size:18px;color:blue}span[data-v-3974490a]{display:flex;justify-content:space-around;width:70px;white-space:nowrap}span i[data-v-3974490a]{font-style:normal}.edit_input[data-v-3974490a]{display:flex;justify-content:space-between;align-items:center;margin:10px 5px} | ||||
| @ -0,0 +1 @@ | ||||
| @font-face{font-family:Cascadia;src:url(../fonts/Cascadia-Code-Regular-2.97c09831.ttf)}.editor{display:flex;align-items:stretch;height:100vh}.left{width:calc(50% - 55px);min-width:500px;display:inline-block}.main{width:100%;height:calc(100vh - 64px);overflow-y:auto}textarea{min-height:20px;flex:1;outline:none;border-radius:4px;border:1px solid #ccc;font-size:14px;font-family:Cascadia,Microsoft YaHei UI,Arial,serif;line-height:20px;padding:10px 10px 10px}.fixed[data-v-ab8a8a34]{position:fixed;top:100px;left:50%;transform:translateX(-50%)}.half-circle-spinner [data-v-ab8a8a34],.half-circle-spinner[data-v-ab8a8a34]{box-sizing:border-box}.half-circle-spinner[data-v-ab8a8a34]{width:60px;height:60px;border-radius:100%;position:relative}.half-circle-spinner .circle[data-v-ab8a8a34]{content:"";position:absolute;width:100%;height:100%;border-radius:100%;border:6px solid transparent}.half-circle-spinner .circle.circle-1[data-v-ab8a8a34]{border-top-color:#ff1d5e;-webkit-animation:half-circle-spinner-animation-ab8a8a34 1s infinite;animation:half-circle-spinner-animation-ab8a8a34 1s infinite}.half-circle-spinner .circle.circle-2[data-v-ab8a8a34]{border-bottom-color:#ff1d5e;-webkit-animation:half-circle-spinner-animation-ab8a8a34 1s infinite alternate;animation:half-circle-spinner-animation-ab8a8a34 1s infinite alternate}@-webkit-keyframes half-circle-spinner-animation-ab8a8a34{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes half-circle-spinner-animation-ab8a8a34{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.warm[data-v-27eae50d]{position:fixed;top:100px;left:50%;transform:translateX(-50%);color:#eee;background-color:#ff1d5e;padding:20px;border-radius:8px;font-size:18px}button[data-v-27eae50d]{float:right;width:70px;height:35px;outline:none;border:unset;border-radius:8px;font-size:14px;transition:background-color .3s ease}.success[data-v-bef92f74],button[data-v-27eae50d]:hover{color:#333;background-color:#7fffd4}.success[data-v-bef92f74]{z-index:3;position:fixed;top:100px;left:50%;transform:translateX(-50%);padding:10px;border-radius:8px}p[data-v-bef92f74]{margin:0}.menu{display:flex;flex-direction:column;justify-content:center}button[data-v-7d09e592]{width:100px;height:50px;margin:5px;outline:none;padding:10px;font-size:16px;border-radius:4px;box-sizing:border-box;border:1px solid #333;background-color:transparent;transition:all .3s ease;overflow:hidden}button span[data-v-7d09e592]{display:inline-block;transform:translateY(20px);opacity:0;font-size:12px;transition:all .3s ease}button[data-v-7d09e592]:hover{color:#fff;background-color:gray}button:hover span[data-v-7d09e592]{transform:translateY(0);opacity:1}textarea[data-v-4301c68c]{font-size:14px}input[data-v-f11ea0d0]{outline:none;height:25px;font-size:16px}textarea[data-v-f11ea0d0]{font-size:14px}.search[data-v-260cb454]{border:1px solid #ddd;border-radius:4px}input[data-v-260cb454]{text-align:center;font-size:16px;height:25px;outline:none}.tool[data-v-260cb454]{display:flex;justify-content:space-around;padding:4px 0}.tool button[data-v-260cb454]{border-radius:4px;padding:5px;outline:none;border:none;flex:1;margin:0 2px}.tool button[data-v-260cb454]:hover{background-color:#ddd}input[type=checkbox][data-v-260cb454]{transform:scale(2);margin:0 15px 0}.book_item[data-v-260cb454]{overflow:hidden;display:flex;align-items:center;margin-top:10px;padding:10px;cursor:pointer;background-color:#eee}.book_active[data-v-260cb454]{background-color:#32cd32}.book_index[data-v-260cb454]{width:auto;height:30px;text-align:center;line-height:30px;border-radius:8px;padding:0 10px;background-color:#ffb6c1}.book_info[data-v-260cb454]{display:flex;justify-content:space-between}.book_list[data-v-260cb454]{height:calc(100vh - 125px);overflow-y:auto}a[data-v-c4c82b2c]{display:block;height:25px;transition:margin-left .3s ease}a[data-v-c4c82b2c]:hover{color:red;margin-left:10px}code[data-v-c4c82b2c]{display:inline-block;font-size:16px;font-family:Cascadia Mono,JetBrains Mono,Microsoft YaHei UI,serif;background-color:#f3f4f4;border-radius:4px}.author[data-v-c4c82b2c]{position:fixed;right:20px;bottom:20px}.author a[data-v-c4c82b2c]{padding:5px 10px;border-radius:4px}.author a[data-v-c4c82b2c]:hover{box-shadow:0 0 3px 3px #ccc;background-color:#ddd}.out{min-width:620px}.out,.out .box{flex:1;display:flex;flex-flow:column}a{text-decoration:none;color:#333}body,ul{margin:0;padding:0}ul{width:100%;height:40px;display:flex}ul li{display:block;text-align:center;line-height:40px;width:16%;list-style:none;cursor:pointer}ul li:hover{color:red}.active{color:#fff!important;background-color:hsla(0,0%,50%,.459);border-bottom:unset!important}ul li[data-v-de4729c0]{border-bottom:2px solid #333}a[data-v-de4729c0]{font-size:18px;color:blue}span[data-v-3974490a]{display:flex;justify-content:space-around;width:70px;white-space:nowrap}span i[data-v-3974490a]{font-style:normal}.edit_input[data-v-3974490a]{display:flex;justify-content:space-between;align-items:center;margin:10px 5px} | ||||
| After Width: | Height: | Size: 4.2 KiB | 
									
										Binary file not shown.
									
								
							
						| @ -1,150 +0,0 @@ | ||||
| body { | ||||
|   margin: 0; | ||||
| } | ||||
| .editor { | ||||
|   display: flex; | ||||
|   align-items: stretch; | ||||
| } | ||||
| .setbox, | ||||
| .menu, | ||||
| .outbox { | ||||
|   flex: 1; | ||||
|   display: flex; | ||||
|   flex-flow: column; | ||||
|   max-height: 100vh; | ||||
|   overflow-y: auto; | ||||
| } | ||||
| .menu { | ||||
|   justify-content: center; | ||||
|   max-width: 90px; | ||||
|   margin: 0 5px; | ||||
| } | ||||
| .menu .button { | ||||
|   width: 90px; | ||||
|   height: 30px; | ||||
|   min-height: 30px; | ||||
|   margin: 5px 0px; | ||||
|   cursor: pointer; | ||||
| } | ||||
| @keyframes stroker { | ||||
|   0% { | ||||
|     stroke-dashoffset: 0; | ||||
|   } | ||||
|   100% { | ||||
|     stroke-dashoffset: -240; | ||||
|   } | ||||
| } | ||||
| .button rect { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   fill: transparent; | ||||
|   stroke: #666; | ||||
|   stroke-width: 2px; | ||||
| } | ||||
| .button rect.busy { | ||||
|   stroke: #fd1850; | ||||
|   stroke-dasharray: 30 90; | ||||
|   animation: stroker 1s linear infinite; | ||||
| } | ||||
| .button text { | ||||
|   text-anchor: middle; | ||||
|   dominant-baseline: middle; | ||||
| } | ||||
| .setbox { | ||||
|   min-width: 40em; | ||||
| } | ||||
| .rules { | ||||
|   overflow: auto; | ||||
| } | ||||
| .tabbox { | ||||
|   flex: 1; | ||||
|   display: flex; | ||||
|   flex-flow: column; | ||||
| } | ||||
| .rules > * { | ||||
|   display: flex; | ||||
|   margin: 2px 0; | ||||
| } | ||||
| .rules textarea { | ||||
|   flex: 1; | ||||
|   margin-left: 5px; | ||||
| } | ||||
| .rules > *, | ||||
| .rules > * > div, | ||||
| .rules textarea { | ||||
|   min-height: 1em; | ||||
| } | ||||
| textarea { | ||||
|   word-break: break-all; | ||||
| } | ||||
| .tabtitle { | ||||
|   display: flex; | ||||
|   z-index: 1; | ||||
|   justify-content: flex-end; | ||||
| } | ||||
| .tabtitle > div { | ||||
|   cursor: pointer; | ||||
|   padding: 1px 10px 0 10px; | ||||
|   border-bottom: 3px solid transparent; | ||||
|   font-weight: bold; | ||||
| } | ||||
| .tabtitle > .this { | ||||
|   color: #4f9da6; | ||||
|   border-bottom-color: #4ebbe4; | ||||
| } | ||||
| .tabbody { | ||||
|   flex: 1; | ||||
|   display: flex; | ||||
|   margin-top: -1px; | ||||
|   border: 1px solid #a9a9a9; | ||||
|   height: 0; | ||||
| } | ||||
| .tabbody > * { | ||||
|   flex: 1; | ||||
|   flex-flow: column; | ||||
|   display: none; | ||||
| } | ||||
| .tabbody > .this { | ||||
|   display: flex; | ||||
| } | ||||
| .tabbody > * > .titlebar { | ||||
|   display: flex; | ||||
| } | ||||
| .tabbody > * > .titlebar > * { | ||||
|   flex: 1; | ||||
|   margin: 1px 1px 1px 1px; | ||||
| } | ||||
| .tabbody > * > .context { | ||||
|   flex: 1; | ||||
|   flex-flow: column; | ||||
|   border: 0; | ||||
|   padding: 5px; | ||||
|   overflow-y: auto; | ||||
| } | ||||
| .tabbody > * > .inputbox { | ||||
|   border: 0; | ||||
|   border-bottom: #a9a9a9 solid 1px; | ||||
|   height: 15px; | ||||
|   text-align: center; | ||||
| } | ||||
| .link > * { | ||||
|   display: flex; | ||||
|   margin: 5px; | ||||
|   border-bottom: 1px solid; | ||||
|   text-decoration: none; | ||||
| } | ||||
| #RuleList > label > * { | ||||
|   background: #eee; | ||||
|   padding-left: 3px; | ||||
|   margin: 2px 0; | ||||
|   cursor: pointer; | ||||
| } | ||||
| #RuleList input[type="radio"] { | ||||
|   display: none; | ||||
| } | ||||
| #RuleList input[type="radio"]:checked + * { | ||||
|   background: #15cda8; | ||||
| } | ||||
| .isError { | ||||
|   color: #ff0000; | ||||
| } | ||||
| @ -1,516 +0,0 @@ | ||||
| // 简化js原生选择器
 | ||||
| function $(selector) { return document.querySelector(selector); } | ||||
| function $$(selector) { return document.querySelectorAll(selector); } | ||||
| // 读写Hash值(val未赋值时为读取)
 | ||||
| function hashParam(key, val) { | ||||
| 	let hashstr = decodeURIComponent(window.location.hash); | ||||
| 	let regKey = new RegExp(`${key}=([^&]*)`); | ||||
| 	let getVal = regKey.test(hashstr) ? hashstr.match(regKey)[1] : null; | ||||
| 	if (val == undefined) return getVal; | ||||
| 	if (hashstr == '' || hashstr == '#') { | ||||
| 		window.location.hash = `#${key}=${val}`; | ||||
| 	} | ||||
| 	else { | ||||
| 		if (getVal) window.location.hash = hashstr.replace(getVal, val); | ||||
| 		else { | ||||
| 			window.location.hash = hashstr.indexOf(key) > -1 ? hashstr.replace(regKey, `${key}=${val}`) : `${hashstr}&${key}=${val}`; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| // 创建源规则容器对象
 | ||||
| function Container() { | ||||
| 	let ruleJson = {}; | ||||
| 	let searchJson = {}; | ||||
| 	let exploreJson = {}; | ||||
| 	let bookInfoJson = {}; | ||||
| 	let tocJson = {}; | ||||
| 	let contentJson = {}; | ||||
| 
 | ||||
| 	// 基本以及其他
 | ||||
| 	$$('.rules .base').forEach(item => ruleJson[item.title] = ''); | ||||
| 	ruleJson.lastUpdateTime = 0; | ||||
| 	ruleJson.customOrder = 0; | ||||
| 	ruleJson.weight = 0; | ||||
| 	ruleJson.enabled = true; | ||||
| 	ruleJson.enabledExplore = true; | ||||
| 
 | ||||
| 	// 搜索规则
 | ||||
| 	$$('.rules .ruleSearch').forEach(item => searchJson[item.title] = ''); | ||||
| 	ruleJson.ruleSearch = searchJson; | ||||
| 
 | ||||
| 	// 发现规则
 | ||||
| 	$$('.rules .ruleExplore').forEach(item => exploreJson[item.title] = ''); | ||||
| 	ruleJson.ruleExplore = exploreJson; | ||||
| 
 | ||||
| 	// 详情页规则
 | ||||
| 	$$('.rules .ruleBookInfo').forEach(item => bookInfoJson[item.title] = ''); | ||||
| 	ruleJson.ruleBookInfo = bookInfoJson; | ||||
| 
 | ||||
| 	// 目录规则
 | ||||
| 	$$('.rules .ruleToc').forEach(item => tocJson[item.title] = ''); | ||||
| 	ruleJson.ruleToc = tocJson; | ||||
| 
 | ||||
| 	// 正文规则
 | ||||
| 	$$('.rules .ruleContent').forEach(item => contentJson[item.title] = ''); | ||||
| 	ruleJson.ruleContent = contentJson; | ||||
| 
 | ||||
| 	return ruleJson; | ||||
| } | ||||
| // 选项卡Tab切换事件处理
 | ||||
| function showTab(tabName) { | ||||
| 	$$('.tabtitle>*').forEach(node => { node.className = node.className.replace(' this', ''); }); | ||||
| 	$$('.tabbody>*').forEach(node => { node.className = node.className.replace(' this', ''); }); | ||||
| 	$(`.tabbody>.${$(`.tabtitle>*[name=${tabName}]`).className}`).className += ' this'; | ||||
| 	$(`.tabtitle>*[name=${tabName}]`).className += ' this'; | ||||
| 	hashParam('tab', tabName); | ||||
| } | ||||
| // 源列表列表标签构造函数
 | ||||
| function newRule(rule) { | ||||
| 	return `<label for="${rule.bookSourceUrl}"><input type="radio" name="rule" id="${rule.bookSourceUrl}"><div>${rule.bookSourceName}<br>${rule.bookSourceUrl}</div></label>`; | ||||
| } | ||||
| // 缓存规则列表
 | ||||
| var RuleSources = []; | ||||
| if (localStorage.getItem('BookSources')) { | ||||
| 	RuleSources = JSON.parse(localStorage.getItem('BookSources')); | ||||
| 	RuleSources.forEach(item => $('#RuleList').innerHTML += newRule(item)); | ||||
| } | ||||
| // 页面加载完成事件
 | ||||
| window.onload = () => { | ||||
| 	$$('.tabtitle>*').forEach(item => { | ||||
| 		item.addEventListener('click', () => { | ||||
| 			showTab(item.innerHTML); | ||||
| 		}); | ||||
| 	}); | ||||
| 	if (hashParam('tab')) showTab(hashParam('tab')); | ||||
| } | ||||
| // 获取数据
 | ||||
| function HttpGet(url) { | ||||
| 	return fetch(hashParam('domain') ? hashParam('domain') + url : url) | ||||
| 		.then(res => res.json()).catch(err => console.error('Error:', err)); | ||||
| } | ||||
| // 提交数据
 | ||||
| function HttpPost(url, data) { | ||||
| 	return fetch(hashParam('domain') ? hashParam('domain') + url : url, { | ||||
| 		body: JSON.stringify(data), | ||||
| 		method: 'POST', | ||||
| 		mode: "cors", | ||||
| 		headers: new Headers({ | ||||
| 			'Content-Type': 'application/json;charset=utf-8' | ||||
| 		}) | ||||
| 	}).then(res => res.json()).catch(err => console.error('Error:', err)); | ||||
| } | ||||
| // 将源表单转化为源对象
 | ||||
| function rule2json() { | ||||
| 	let RuleJSON = Container(); | ||||
| 	// 转换base
 | ||||
| 	Object.keys(RuleJSON).forEach(key => { | ||||
| 		if (!key.startsWith("rule")) { | ||||
| 			RuleJSON[key] = $('#' + key).value; | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	// 转换搜索规则
 | ||||
| 	let searchJson = {}; | ||||
| 	Object.keys(RuleJSON.ruleSearch).forEach(key => { | ||||
| 		if ($('#' + 'ruleSearch_' + key).value) | ||||
| 			searchJson[key] = $('#' + 'ruleSearch_' + key).value; | ||||
| 	}); | ||||
| 	RuleJSON.ruleSearch = searchJson; | ||||
| 
 | ||||
| 	// 转换发现规则
 | ||||
| 	let exploreJson = {}; | ||||
| 	Object.keys(RuleJSON.ruleExplore).forEach(key => { | ||||
| 		if ($('#' + 'ruleExplore_' + key).value) | ||||
| 			exploreJson[key] = $('#' + 'ruleExplore_' + key).value; | ||||
| 	}); | ||||
| 	RuleJSON.ruleExplore = exploreJson; | ||||
| 
 | ||||
| 	// 转换详情页规则
 | ||||
| 	let bookInfoJson = {}; | ||||
| 	Object.keys(RuleJSON.ruleBookInfo).forEach(key => { | ||||
| 		if ($('#' + 'ruleBookInfo_' + key).value) | ||||
| 			bookInfoJson[key] = $('#' + 'ruleBookInfo_' + key).value; | ||||
| 	}); | ||||
| 	RuleJSON.ruleBookInfo = bookInfoJson; | ||||
| 
 | ||||
| 	// 转换目录规则
 | ||||
| 	let tocJson = {}; | ||||
| 	Object.keys(RuleJSON.ruleToc).forEach(key => { | ||||
| 		if ($('#' + 'ruleToc_' + key).value) | ||||
| 			tocJson[key] = $('#' + 'ruleToc_' + key).value; | ||||
| 	}); | ||||
| 	RuleJSON.ruleToc = tocJson; | ||||
| 
 | ||||
| 	// 转换正文规则
 | ||||
| 	let contentJson = {}; | ||||
| 	Object.keys(RuleJSON.ruleContent).forEach(key => { | ||||
| 		if ($('#' + 'ruleContent_' + key).value) | ||||
| 			contentJson[key] = $('#' + 'ruleContent_' + key).value; | ||||
| 	}); | ||||
| 	RuleJSON.ruleContent = contentJson; | ||||
| 
 | ||||
| 	RuleJSON.lastUpdateTime = new Date().getTime(); | ||||
| 	RuleJSON.customOrder = RuleJSON.customOrder == '' ? 0 : parseInt(RuleJSON.customOrder); | ||||
| 	RuleJSON.weight = RuleJSON.weight == '' ? 0 : parseInt(RuleJSON.weight); | ||||
| 	RuleJSON.bookSourceType == RuleJSON.bookSourceType == '' ? 0 : parseInt(RuleJSON.bookSourceType); | ||||
| 	RuleJSON.enabled = RuleJSON.enabled == '' || String(RuleJSON.enabled).toLocaleLowerCase().replace(/^\s*|\s*$/g, '') == 'true'; | ||||
| 	RuleJSON.enabledExplore = RuleJSON.enabledExplore == '' || String(RuleJSON.enabledExplore).toLocaleLowerCase().replace(/^\s*|\s*$/g, '') == 'true'; | ||||
| 	return RuleJSON; | ||||
| } | ||||
| // 将源对象填充到源表单
 | ||||
| function json2rule(RuleEditor) { | ||||
| 	let RuleJSON = Container(); | ||||
| 	// 转换base
 | ||||
| 	Object.keys(RuleJSON).forEach(key => { | ||||
| 		if (!key.startsWith("rule")) { | ||||
| 			let val = RuleEditor[key]; | ||||
| 			if (typeof val == "number") { | ||||
| 				$("#" + key).value = val ? String(val) : '0'; | ||||
| 			} | ||||
| 			else if (typeof val == "boolean") { | ||||
| 				$("#" + key).value = val ? String(val) : 'false'; | ||||
| 			} | ||||
| 			else { | ||||
| 				$("#" + key).value = val ? String(val) : ''; | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	// 转换搜索规则
 | ||||
| 	if (RuleEditor.ruleSearch) { | ||||
| 		let searchJson = RuleEditor.ruleSearch; | ||||
| 		Object.keys(RuleJSON.ruleSearch).forEach(key => { | ||||
| 			$('#' + 'ruleSearch_' + key).value = searchJson[key] ? searchJson[key] : ''; | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	// 转换发现规则
 | ||||
| 	if (RuleEditor.ruleExplore) { | ||||
| 		let exploreJson = RuleEditor.ruleExplore; | ||||
| 		Object.keys(RuleJSON.ruleExplore).forEach(key => { | ||||
| 			$('#' + 'ruleExplore_' + key).value = exploreJson[key] ? exploreJson[key] : ''; | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	// 转换详情页规则
 | ||||
| 	if (RuleEditor.ruleBookInfo) { | ||||
| 		let bookInfoJson = RuleEditor.ruleBookInfo; | ||||
|         Object.keys(RuleJSON.ruleBookInfo).forEach(key => { | ||||
| 			$('#' + 'ruleBookInfo_' + key).value = bookInfoJson[key] ? bookInfoJson[key] : ''; | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	// 转换目录规则
 | ||||
| 	if (RuleEditor.ruleToc) { | ||||
| 		let tocJson = RuleEditor.ruleToc; | ||||
| 		Object.keys(RuleJSON.ruleToc).forEach(key => { | ||||
| 			$('#' + 'ruleToc_' + key).value = tocJson[key] ? tocJson[key] : ''; | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	// 转换正文规则
 | ||||
| 	if (RuleEditor.ruleContent) { | ||||
| 		let contentJson = RuleEditor.ruleContent; | ||||
|         Object.keys(RuleJSON.ruleContent).forEach(key => { | ||||
| 			$('#' + 'ruleContent_' + key).value = contentJson[key] ? contentJson[key] : ''; | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| // 记录操作过程
 | ||||
| var course = { "old": [], "now": {}, "new": [] }; | ||||
| if (localStorage.getItem('bookSourceCourse')) { | ||||
| 	course = JSON.parse(localStorage.getItem('bookSourceCourse')); | ||||
| 	json2rule(course.now); | ||||
| } | ||||
| else { | ||||
| 	course.now = rule2json(); | ||||
| 	window.localStorage.setItem('bookSourceCourse', JSON.stringify(course)); | ||||
| } | ||||
| function todo() { | ||||
| 	course.old.push(Object.assign({}, course.now)); | ||||
| 	course.now = rule2json(); | ||||
| 	course.new = []; | ||||
| 	if (course.old.length > 50) course.old.shift(); // 限制历史记录堆栈大小
 | ||||
| 	localStorage.setItem('bookSourceCourse', JSON.stringify(course)); | ||||
| } | ||||
| function undo() { | ||||
| 	course = JSON.parse(localStorage.getItem('bookSourceCourse')); | ||||
| 	if (course.old.length > 0) { | ||||
| 		course.new.push(course.now); | ||||
| 		course.now = course.old.pop(); | ||||
| 		localStorage.setItem('bookSourceCourse', JSON.stringify(course)); | ||||
| 		json2rule(course.now); | ||||
| 	} | ||||
| } | ||||
| function redo() { | ||||
| 	course = JSON.parse(localStorage.getItem('bookSourceCourse')); | ||||
| 	if (course.new.length > 0) { | ||||
| 		course.old.push(course.now); | ||||
| 		course.now = course.new.pop(); | ||||
| 		localStorage.setItem('bookSourceCourse', JSON.stringify(course)); | ||||
| 		json2rule(course.now); | ||||
| 	} | ||||
| } | ||||
| function setRule(editRule) { | ||||
| 	let checkRule = RuleSources.find(x => x.bookSourceUrl == editRule.bookSourceUrl); | ||||
| 	if ($(`input[id="${editRule.bookSourceUrl}"]`)) { | ||||
| 		Object.keys(checkRule).forEach(key => { checkRule[key] = editRule[key]; }); | ||||
| 		$(`input[id="${editRule.bookSourceUrl}"]+*`).innerHTML = `${editRule.bookSourceName}<br>${editRule.bookSourceUrl}`; | ||||
| 	} else { | ||||
| 		RuleSources.push(editRule); | ||||
| 		$('#RuleList').innerHTML += newRule(editRule); | ||||
| 	} | ||||
| } | ||||
| $$('input').forEach((item) => { item.addEventListener('change', () => { todo() }) }); | ||||
| $$('textarea').forEach((item) => { item.addEventListener('change', () => { todo() }) }); | ||||
| // 处理按钮点击事件
 | ||||
| $('.menu').addEventListener('click', e => { | ||||
| 	let thisNode = e.target; | ||||
| 	thisNode = thisNode.parentNode.nodeName == 'svg' ? thisNode.parentNode.querySelector('rect') : | ||||
| 		thisNode.nodeName == 'svg' ? thisNode.querySelector('rect') : null; | ||||
| 	if (!thisNode) return; | ||||
| 	if (thisNode.getAttribute('class') == 'busy') return; | ||||
| 	thisNode.setAttribute('class', 'busy'); | ||||
| 	switch (thisNode.id) { | ||||
| 		case 'push': | ||||
| 			$$('#RuleList>label>div').forEach(item => { item.className = ''; }); | ||||
| 			(async () => { | ||||
| 				await HttpPost(`/saveBookSources`, RuleSources).then(json => { | ||||
| 					if (json.isSuccess) { | ||||
| 						let okData = json.data; | ||||
| 						if (Array.isArray(okData)) { | ||||
| 							let failMsg = ``; | ||||
| 							if (RuleSources.length > okData.length) { | ||||
| 								RuleSources.forEach(item => { | ||||
| 									if (okData.find(x => x.bookSourceUrl == item.bookSourceUrl)) { } | ||||
| 									else { $(`#RuleList #${item.bookSourceUrl}+*`).className += 'isError'; } | ||||
| 								}); | ||||
| 								failMsg = '\n推送失败的源将用红色字体标注!'; | ||||
| 							} | ||||
| 							alert(`批量推送源到「阅读3.0APP」\n共计: ${RuleSources.length} 条\n成功: ${okData.length} 条\n失败: ${RuleSources.length - okData.length} 条${failMsg}`); | ||||
| 						} | ||||
| 						else { | ||||
| 							alert(`批量推送源到「阅读3.0APP」成功!\n共计: ${RuleSources.length} 条`); | ||||
| 						} | ||||
| 					} | ||||
| 					else { | ||||
| 						alert(`批量推送源失败!\nErrorMsg: ${json.errorMsg}`); | ||||
| 					} | ||||
| 				}).catch(err => { alert(`批量推送源失败,无法连接到「阅读3.0APP」!\n${err}`); }); | ||||
| 				thisNode.setAttribute('class', ''); | ||||
| 			})(); | ||||
| 			return; | ||||
| 		case 'pull': | ||||
| 			showTab('源列表'); | ||||
| 			(async () => { | ||||
| 				await HttpGet(`/getBookSources`).then(json => { | ||||
| 					if (json.isSuccess) { | ||||
| 						$('#RuleList').innerHTML = '' | ||||
| 						localStorage.setItem('BookSources', JSON.stringify(RuleSources = json.data)); | ||||
| 						RuleSources.forEach(item => { | ||||
| 							$('#RuleList').innerHTML += newRule(item); | ||||
| 						}); | ||||
| 						alert(`成功拉取 ${RuleSources.length} 条源`); | ||||
| 					} | ||||
| 					else { | ||||
| 						alert(`批量拉取源失败!\nErrorMsg: ${json.errorMsg}`); | ||||
| 					} | ||||
| 				}).catch(err => { alert(`批量拉取源失败,无法连接到「阅读3.0APP」!\n${err}`); }); | ||||
| 				thisNode.setAttribute('class', ''); | ||||
| 			})(); | ||||
| 			return; | ||||
| 		case 'editor': | ||||
| 			if ($('#RuleJsonString').value == '') break; | ||||
| 			try { | ||||
| 				json2rule(JSON.parse($('#RuleJsonString').value)); | ||||
| 				todo(); | ||||
| 			} catch (error) { | ||||
| 				console.log(error); | ||||
| 				alert(error); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'conver': | ||||
| 			showTab('编辑源'); | ||||
| 			$('#RuleJsonString').value = JSON.stringify(rule2json(), null, 4); | ||||
| 			break; | ||||
| 		case 'initial': | ||||
| 			$$('.rules textarea').forEach(item => { item.value = '' }); | ||||
| 			todo(); | ||||
| 			break; | ||||
| 		case 'undo': | ||||
| 			undo() | ||||
| 			break; | ||||
| 		case 'redo': | ||||
| 			redo() | ||||
| 			break; | ||||
| 		case 'debug': | ||||
| 			showTab('调试源'); | ||||
| 			let wsOrigin = (hashParam('domain') || location.origin).replace(/^.*?:/, 'ws:').replace(/\d+$/, (port) => (parseInt(port) + 1)); | ||||
| 			let DebugInfos = $('#DebugConsole'); | ||||
| 			function DebugPrint(msg) { DebugInfos.value += `\n${msg}`; DebugInfos.scrollTop = DebugInfos.scrollHeight; } | ||||
| 			let saveRule = [rule2json()]; | ||||
| 			HttpPost(`/saveBookSources`, saveRule).then(sResult => { | ||||
| 				if (sResult.isSuccess) { | ||||
| 					let sKey = DebugKey.value ? DebugKey.value : '我的'; | ||||
| 					$('#DebugConsole').value = `源《${saveRule[0].bookSourceName}》保存成功!使用搜索关键字“${sKey}”开始调试...`; | ||||
| 					let ws = new WebSocket(`${wsOrigin}/bookSourceDebug`); | ||||
| 					ws.onopen = () => { | ||||
| 						ws.send(`{"tag":"${saveRule[0].bookSourceUrl}", "key":"${sKey}"}`); | ||||
| 					}; | ||||
| 					ws.onmessage = (msg) => { | ||||
| 					    console.log('[调试]', msg); | ||||
| 						DebugPrint(msg.data); | ||||
| 					}; | ||||
| 					ws.onerror = (err) => { | ||||
| 						throw `${err.data}`; | ||||
| 					} | ||||
| 					ws.onclose = () => { | ||||
| 						thisNode.setAttribute('class', ''); | ||||
| 						DebugPrint(`\n调试服务已关闭!`); | ||||
| 					} | ||||
| 				} else throw `${sResult.errorMsg}`; | ||||
| 			}).catch(err => { | ||||
| 				DebugPrint(`调试过程意外中止,以下是详细错误信息:\n${err}`); | ||||
| 				thisNode.setAttribute('class', ''); | ||||
| 			}); | ||||
| 			return; | ||||
| 		case 'accept': | ||||
| 			(async () => { | ||||
| 				let saveRule = [rule2json()]; | ||||
| 				await HttpPost(`/saveBookSource`, saveRule[0]).then(json => { | ||||
| 					alert(json.isSuccess ? `源《${saveRule[0].bookSourceName}》已成功保存到「阅读3.0APP」` : `源《${saveRule[0].bookSourceName}》保存失败!\nErrorMsg: ${json.errorMsg}`); | ||||
| 					setRule(saveRule[0]); | ||||
| 				}).catch(err => { alert(`保存源失败,无法连接到「阅读3.0APP」!\n${err}`); }); | ||||
| 				thisNode.setAttribute('class', ''); | ||||
| 			})(); | ||||
| 			return; | ||||
| 		default: | ||||
| 	} | ||||
| 	setTimeout(() => { thisNode.setAttribute('class', ''); }, 500); | ||||
| }); | ||||
| $('#DebugKey').addEventListener('keydown', e => { | ||||
| 	if (e.keyCode == 13) { | ||||
| 		let clickEvent = document.createEvent('MouseEvents'); | ||||
| 		clickEvent.initEvent("click", true, false); | ||||
| 		$('#debug').dispatchEvent(clickEvent); | ||||
| 	} | ||||
| }); | ||||
| $('#Filter').addEventListener('keydown', e => { | ||||
| 	if (e.keyCode == 13) { | ||||
| 		let cashList = []; | ||||
| 		$('#RuleList').innerHTML = ""; | ||||
| 		let sKey = Filter.value ? Filter.value : ''; | ||||
| 		if (sKey == '') { | ||||
| 			cashList = RuleSources; | ||||
| 		} else { | ||||
| 			let patt = new RegExp(sKey); | ||||
| 			RuleSources.forEach(source => { | ||||
| 				if (patt.test(source.bookSourceUrl) || patt.test(source.bookSourceName) || patt.test(source.bookSourceGroup)) { | ||||
| 					cashList.push(source); | ||||
| 				} | ||||
| 			}) | ||||
| 		} | ||||
| 		cashList.forEach(source => { | ||||
| 			$('#RuleList').innerHTML += newRule(source); | ||||
| 		}) | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| // 列表规则更改事件
 | ||||
| $('#RuleList').addEventListener('click', e => { | ||||
| 	let editRule = null; | ||||
| 	if (e.target && e.target.getAttribute('name') == 'rule') { | ||||
| 		editRule = rule2json(); | ||||
| 		json2rule(RuleSources.find(x => x.bookSourceUrl == e.target.id)); | ||||
| 	} else return; | ||||
| 	if (editRule.bookSourceUrl == '') return; | ||||
| 	if (editRule.bookSourceName == '') editRule.bookSourceName = editRule.bookSourceUrl.replace(/.*?\/\/|\/.*/g, ''); | ||||
| 	setRule(editRule); | ||||
| 	localStorage.setItem('BookSources', JSON.stringify(RuleSources)); | ||||
| }); | ||||
| // 处理列表按钮事件
 | ||||
| $('.tab3>.titlebar').addEventListener('click', e => { | ||||
| 	let thisNode = e.target; | ||||
| 	if (thisNode.nodeName != 'BUTTON') return; | ||||
| 	switch (thisNode.id) { | ||||
| 		case 'Import': | ||||
| 			let fileImport = document.createElement('input'); | ||||
| 			fileImport.type = 'file'; | ||||
| 			fileImport.accept = '.json'; | ||||
| 			fileImport.addEventListener('change', () => { | ||||
| 				let file = fileImport.files[0]; | ||||
| 				let reader = new FileReader(); | ||||
| 				reader.onloadend = function (evt) { | ||||
| 					if (evt.target.readyState == FileReader.DONE) { | ||||
| 						let fileText = evt.target.result; | ||||
| 						try { | ||||
| 							let fileJson = JSON.parse(fileText); | ||||
| 							let newSources = []; | ||||
| 							newSources.push(...fileJson); | ||||
| 							if (window.confirm(`如何处理导入的源?\n"确定": 覆盖当前列表(不会删除APP源)\n"取消": 插入列表尾部(自动忽略重复源)`)) { | ||||
| 								localStorage.setItem('BookSources', JSON.stringify(RuleSources = newSources)); | ||||
| 								$('#RuleList').innerHTML = '' | ||||
| 								RuleSources.forEach(item => { | ||||
| 									$('#RuleList').innerHTML += newRule(item); | ||||
| 								}); | ||||
| 							} | ||||
| 							else { | ||||
| 								newSources = newSources.filter(item => !JSON.stringify(RuleSources).includes(item.bookSourceUrl)); | ||||
| 								RuleSources.push(...newSources); | ||||
| 								localStorage.setItem('BookSources', JSON.stringify(RuleSources)); | ||||
| 								newSources.forEach(item => { | ||||
| 									$('#RuleList').innerHTML += newRule(item); | ||||
| 								}); | ||||
| 							} | ||||
| 							alert(`成功导入 ${newSources.length} 条源`); | ||||
| 						} | ||||
| 						catch (err) { | ||||
| 							alert(`导入源文件失败!\n${err}`); | ||||
| 						} | ||||
| 					} | ||||
| 				}; | ||||
| 				reader.readAsText(file); | ||||
| 			}, false); | ||||
| 			fileImport.click(); | ||||
| 			break; | ||||
| 		case 'Export': | ||||
| 			let fileExport = document.createElement('a'); | ||||
| 			fileExport.download = `Rules${Date().replace(/.*?\s(\d+)\s(\d+)\s(\d+:\d+:\d+).*/, '$2$1$3').replace(/:/g, '')}.json`; | ||||
| 			let myBlob = new Blob([JSON.stringify(RuleSources, null, 4)], { type: "application/json" }); | ||||
| 			fileExport.href = window.URL.createObjectURL(myBlob); | ||||
| 			fileExport.click(); | ||||
| 			break; | ||||
| 		case 'Delete': | ||||
| 			let selectRule = $('#RuleList input:checked'); | ||||
| 			if (!selectRule) { | ||||
| 				alert(`没有源被选中!`); | ||||
| 				return; | ||||
| 			} | ||||
| 			if (confirm(`确定要删除选定源吗?\n(同时删除APP内源)`)) { | ||||
| 				let selectRuleUrl = selectRule.id; | ||||
| 				let deleteSources = RuleSources.filter(item => item.bookSourceUrl == selectRuleUrl); // 提取待删除的源
 | ||||
| 				let laveSources = RuleSources.filter(item => !(item.bookSourceUrl == selectRuleUrl));  // 提取待留下的源
 | ||||
| 				HttpPost(`/deleteBookSources`, deleteSources).then(json => { | ||||
| 					if (json.isSuccess) { | ||||
| 						let selectNode = document.getElementById(selectRuleUrl).parentNode; | ||||
| 						selectNode.parentNode.removeChild(selectNode); | ||||
| 						localStorage.setItem('BookSources', JSON.stringify(RuleSources = laveSources)); | ||||
| 						if ($('#bookSourceUrl').value == selectRuleUrl) { | ||||
| 							$$('.rules textarea').forEach(item => { item.value = '' }); | ||||
| 							todo(); | ||||
| 						} | ||||
| 						console.log(deleteSources); | ||||
| 						console.log(`以上源已删除!`) | ||||
| 					} | ||||
| 				}).catch(err => { alert(`删除源失败,无法连接到「阅读3.0APP」!\n${err}`); }); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'ClrAll': | ||||
| 			if (confirm(`确定要清空当前源列表吗?\n(不会删除APP内源)`)) { | ||||
| 				localStorage.setItem('BookSources', JSON.stringify(RuleSources = [])); | ||||
| 				$('#RuleList').innerHTML = '' | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 	} | ||||
| }); | ||||
									
										
											File diff suppressed because one or more lines are too long
										
									
								
							
						
									
										
											File diff suppressed because one or more lines are too long
										
									
								
							
						
									
										
											File diff suppressed because one or more lines are too long
										
									
								
							
						
									
										
											File diff suppressed because one or more lines are too long
										
									
								
							
						
									
										
											File diff suppressed because one or more lines are too long
										
									
								
							
						
									
										
											File diff suppressed because one or more lines are too long
										
									
								
							
						| @ -0,0 +1,45 @@ | ||||
| package io.legado.app.help.config | ||||
| 
 | ||||
| import android.content.Context.MODE_PRIVATE | ||||
| import androidx.core.content.edit | ||||
| import splitties.init.appCtx | ||||
| 
 | ||||
| object SourceConfig { | ||||
|     private val sp = appCtx.getSharedPreferences("SourceConfig", MODE_PRIVATE) | ||||
|     fun setBookScore(origin: String, name: String, author: String, score: Int) { | ||||
|         sp.edit { | ||||
|             val preScore = getBookScore(origin, name, author) | ||||
|             var newScore = score | ||||
|             if (preScore != 0) { | ||||
|                 newScore = score - preScore | ||||
|             } | ||||
| 
 | ||||
|             putInt(origin, getSourceScore(origin) + newScore) | ||||
| 
 | ||||
|             putInt("${origin}_${name}_${author}", score) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun getBookScore(origin: String, name: String, author: String): Int { | ||||
|         return sp.getInt("${origin}_${name}_${author}", 0) | ||||
|     } | ||||
| 
 | ||||
|     fun getSourceScore(origin: String): Int { | ||||
|         return sp.getInt(origin, 0) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     fun removeSource(origin: String) { | ||||
|         sp.all.keys.filter { | ||||
|             it.startsWith(origin) | ||||
|         }.let { | ||||
|             sp.edit { | ||||
|                 it.forEach { | ||||
|                     remove(it) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,15 @@ | ||||
| package io.legado.app.utils | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.animation.Animation | ||||
| import android.view.animation.AnimationUtils | ||||
| import androidx.annotation.AnimRes | ||||
| import io.legado.app.help.config.AppConfig | ||||
| 
 | ||||
| fun loadAnimation(context: Context, @AnimRes id: Int): Animation { | ||||
|     val animation = AnimationUtils.loadAnimation(context, id) | ||||
|     if (AppConfig.isEInkMode) { | ||||
|         animation.duration = 0 | ||||
|     } | ||||
|     return animation | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| package io.legado.app.utils | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.animation.Animation | ||||
| import android.view.animation.AnimationUtils | ||||
| import androidx.annotation.AnimRes | ||||
| import io.legado.app.help.config.AppConfig | ||||
| 
 | ||||
| object AnimationUtilsSupport { | ||||
|     fun loadAnimation(context: Context, @AnimRes id: Int): Animation { | ||||
|         val animation = AnimationUtils.loadAnimation(context, id) | ||||
|         if (AppConfig.isEInkMode) { | ||||
|             animation.duration = 0 | ||||
|         } | ||||
|         return animation | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| <vector android:height="24dp" android:viewportHeight="1024" | ||||
|     android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <path android:fillColor="#FF000000" android:pathData="M939.4,423.4c-23,-37.3 -62.9,-60.8 -107,-63.2 -2.8,-0.4 -5.5,-0.6 -8.3,-0.6l-152.2,-0.1c6.6,-29 10,-58.7 10,-88.7 0,-28.2 -3.2,-57.1 -9.6,-86 -0.4,-2 -1.1,-4 -1.9,-5.9 -15.8,-57.3 -67.4,-96.8 -127.3,-96.8 -72.8,0 -132.1,59.3 -132.1,132.1 0,3.3 0.1,6.7 0.4,10 -2.2,57.2 -32.1,109.9 -80.3,141.4 -14.4,9.4 -18.5,28.8 -9.1,43.2 9.4,14.4 28.8,18.5 43.2,9.1 65.8,-42.9 106.4,-115.3 108.7,-193.7 0,-1.3 -0,-2.7 -0.1,-4 -0.2,-2 -0.3,-4 -0.3,-6 0,-38.4 31.2,-69.6 69.6,-69.6 32.6,0 60.5,22.2 67.8,54 0.4,1.5 0.8,3 1.4,4.5 4.7,22.8 7.1,45.6 7.1,67.7 0,37.5 -6.2,74.4 -18.5,109.6 -3.3,9.5 -1.8,20.1 4,28.3 5.9,8.2 15.3,13.1 25.4,13.2l193.2,0.1c1.4,0.3 2.9,0.4 4.3,0.5 24.1,1 45.9,13.6 58.6,34.1 7.8,12.3 11.4,26.8 10.4,41.9 -0.1,0.9 -0.1,1.9 -0.1,2.9 0,0.9 0,1.7 0.1,2.5 0,0.3 -0,0.7 -0.1,1 -0.1,0.4 -0.2,0.8 -0.3,1.2l-75,330.4c-0.9,1.3 -1.7,2.6 -2.4,4 -5.9,11.8 -14.7,21.5 -25.3,28.2 -10.7,6.8 -23.1,10.6 -35.8,11.1 -0.9,-0.1 -513.8,-0.2 -513.8,-0.2 -0.5,-0 -0.9,-0 -1.4,-0 0,0 -111,0.2 -112.7,0.5 -1.9,0 -3.4,-1.5 -3.4,-3.4l0.3,-416.3c0,-1.9 1.5,-3.4 3,-3.5l1.2,0.1c1.2,0.1 2.7,0.3 3.5,0.2l83.8,-0.2 0,339.4c0,17.3 14,31.2 31.2,31.2s31.2,-14 31.2,-31.2L281,435.4c0,-1.8 0,-8.6 0,-10.4 0,-17.3 -14,-30.9 -31.2,-30.9 -1.5,0 -117.5,0.3 -119.4,0.3 -36.3,0 -65.9,29.6 -65.9,65.9l-0.3,416.3c0,36.3 29.6,65.9 65.9,65.9 2.5,0 111.4,-0.5 111.4,-0.5 0.5,0 0.9,0 1.4,0 0,0 511.5,0.3 512.5,0.3 25.5,0 50.3,-7.2 71.6,-20.7 19.6,-12.3 35.8,-29.9 46.8,-51 3.7,-5.6 6.4,-11.9 8.3,-18.6 0.1,-0.4 0.2,-0.8 0.3,-1.2l74.9,-330.3c1.6,-6.2 2.3,-12.6 2,-19C960.9,473.4 953.9,446.3 939.4,423.4z"/> | ||||
|     <path android:fillColor="#FF000000" android:pathData="M450,518.7c-17.3,0 -31.2,14 -31.2,31.2l0,30.5c0,17.3 14,31.2 31.2,31.2 17.3,0 31.2,-14 31.2,-31.2l0,-30.5C481.3,532.6 467.3,518.7 450,518.7z"/> | ||||
|     <path android:fillColor="#FF000000" android:pathData="M693.8,518.7c-17.3,0 -31.2,14 -31.2,31.2l0,30.5c0,17.3 14,31.2 31.2,31.2 17.3,0 31.2,-14 31.2,-31.2l0,-30.5C725,532.6 711.1,518.7 693.8,518.7z"/> | ||||
|     <path android:fillColor="#FF000000" android:pathData="M648.9,660.1c-14.3,-9.4 -33.6,-5.4 -43.2,8.8 -0.1,0.2 -13.6,19.8 -34.2,19.8 -20,0 -32.4,-18.1 -33.3,-19.4 -9.2,-14.4 -28.3,-18.8 -42.8,-9.8 -14.7,9.1 -19.2,28.4 -10.1,43 11.2,18 42,48.6 86.2,48.6 44,0 75.1,-30.3 86.6,-48.2C667.4,688.5 663.2,669.5 648.9,660.1z"/> | ||||
| </vector> | ||||
| @ -1,56 +1,87 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:background="?android:attr/selectableItemBackground" | ||||
|     android:paddingLeft="10dp" | ||||
|     android:paddingTop="10dp" | ||||
|     android:paddingBottom="10dp" | ||||
|     tools:ignore="RtlHardcoded,RtlSymmetry"> | ||||
| 
 | ||||
|     <androidx.appcompat.widget.AppCompatImageView | ||||
|         android:id="@+id/iv_good" | ||||
|         android:layout_width="30dp" | ||||
|         android:layout_height="0dp" | ||||
|         android:layout_marginTop="5dp" | ||||
|         android:padding="5dp" | ||||
|         android:src="@drawable/ic_praise" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/iv_bad" | ||||
|         app:layout_constraintLeft_toLeftOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:tint="@color/md_red_A200" /> | ||||
| 
 | ||||
|     <androidx.appcompat.widget.AppCompatImageView | ||||
|         android:id="@+id/iv_bad" | ||||
|         android:layout_width="30dp" | ||||
|         android:layout_height="0dp" | ||||
|         android:layout_marginBottom="5dp" | ||||
|         android:padding="5dp" | ||||
|         android:rotationX="180" | ||||
|         android:src="@drawable/ic_praise" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintLeft_toLeftOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/iv_good" | ||||
|         app:tint="@color/md_blue_A200" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/tv_origin" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginLeft="30dp" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:singleLine="true" | ||||
|         android:textColor="@color/primaryText" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:layout_constraintLeft_toLeftOf="parent" | ||||
|         app:layout_constraintRight_toLeftOf="@+id/tv_author" /> | ||||
|         app:layout_constraintRight_toLeftOf="@+id/tv_author" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/tv_author" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:maxWidth="160dp" | ||||
|         android:singleLine="true" | ||||
|         android:textColor="@color/secondaryText" | ||||
|         android:maxWidth="160dp" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:layout_constraintRight_toLeftOf="@+id/iv_checked" /> | ||||
|         app:layout_constraintRight_toLeftOf="@+id/iv_checked" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/tv_last" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginLeft="30dp" | ||||
|         android:layout_marginBottom="10dp" | ||||
|         android:singleLine="true" | ||||
|         android:textColor="@color/secondaryText" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/tv_origin" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintLeft_toLeftOf="parent" | ||||
|         app:layout_constraintRight_toLeftOf="@+id/iv_checked" /> | ||||
|         app:layout_constraintRight_toLeftOf="@+id/iv_checked" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/tv_origin" /> | ||||
| 
 | ||||
|     <androidx.appcompat.widget.AppCompatImageView | ||||
|         android:id="@+id/iv_checked" | ||||
|         android:layout_width="40dp" | ||||
|         android:layout_height="40dp" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:layout_marginBottom="10dp" | ||||
|         android:padding="8dp" | ||||
|         android:src="@drawable/ic_check" | ||||
|         android:visibility="invisible" | ||||
|         app:tint="@color/primaryText" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintRight_toRightOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" /> | ||||
|         app:tint="@color/primaryText" | ||||
|         tools:visibility="visible" /> | ||||
| 
 | ||||
| 
 | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
Some files were not shown because too many files have changed in this diff Show More
					Loading…
					
					
				
		Reference in new issue