Merge branch 'gedoor:master' into master
This commit is contained in:
commit
5712b755fe
115 files changed
+1055
-1521
No files matched your search
@@ -32,3 +32,9 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
registries: "*"
|
||||
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
if: ${{ github.event.repository.owner.id == github.event.sender.id && github.actor != 'gedoor' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install git
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.actor == 'gedoor' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
echo "PR_BODY=Changes in the [Git log](https://chromium.googlesource.com/chromium/src/+log/$current_cronet_version..$lastest_cronet_version)" >> $GITHUB_ENV
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
token: ${{ secrets.ACTIONS_TOKEN }}
|
||||
|
||||
@@ -42,11 +42,11 @@ jobs:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
play: ${{ needs.prepare.outputs.play }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@@ -81,14 +81,14 @@ jobs:
|
||||
cp -rf ${{ github.workspace }}/app/build/outputs/apk/*/*/*.apk ${{ github.workspace }}/apk/
|
||||
|
||||
- name: Upload App To Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: legado_${{ env.product }}
|
||||
path: ${{ github.workspace }}/apk/*.apk
|
||||
|
||||
- name: Release
|
||||
if: ${{ env.product == 'app' }}
|
||||
uses: softprops/action-gh-release@59c3b4891632ff9a897f99a91d7bc557467a3a22
|
||||
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
|
||||
with:
|
||||
name: legado_app_${{ env.VERSION }}
|
||||
tag_name: ${{ env.VERSION }}
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: '由于长期没有状态更新,该问题将于5天后自动关闭。如有需要可重新打开。'
|
||||
|
||||
@@ -47,10 +47,10 @@ jobs:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
VERSIONL: ${{ needs.prepare.outputs.versionL }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
mv "$file" ${{ github.workspace }}/apk/legado_${{ env.product }}_${{ env.VERSIONL }}_$typeName.apk
|
||||
done
|
||||
- name: Upload App To Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: legado.${{ env.product }}.${{ env.type }}
|
||||
path: ${{ github.workspace }}/apk/*.apk
|
||||
@@ -106,8 +106,8 @@ jobs:
|
||||
# 蓝奏云里的文件夹ID(阅读3测试版:2670621)
|
||||
LANZOU_FOLDER_ID: '2670621'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: apk/
|
||||
- working-directory: apk/
|
||||
@@ -124,8 +124,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' && github.actor == 'gedoor' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: apk/
|
||||
- working-directory: apk/
|
||||
@@ -150,8 +150,8 @@ jobs:
|
||||
CHANNEL_ID: ${{ secrets.CHANNEL_ID }}
|
||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: apk/
|
||||
- working-directory: apk/
|
||||
|
||||
+22
-12
@@ -1,9 +1,6 @@
|
||||
# [English](English.md) [中文](README.md)
|
||||
|
||||
[](https://play.google.com/store/apps/details?id=io.legado.play.release)
|
||||
<a href="https://data.newrank.cn/m/s.html?s=NykyOzI9MS5LNQ%3D%3D" target="_blank">
|
||||
<img src="https://img.shields.io/badge/-微信关注“开源阅读”公众号-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
<div align="center">
|
||||
<img width="125" height="125" src="https://github.com/gedoor/legado/raw/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png" alt="legado"/>
|
||||
@@ -49,65 +46,76 @@ You can customize the book source, set your own rules, and capture web page data
|
||||
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right">
|
||||
<img src="https://img.shields.io/badge/-Top-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
# Download [](#Download-)
|
||||
|
||||
#### Android
|
||||
|
||||
* [Releases](https://github.com/gedoor/legado/releases/latest)
|
||||
* [Google play - $1.99](https://play.google.com/store/apps/details?id=io.legado.play.release)
|
||||
* [Coolapk](https://www.coolapk.com/apk/io.legado.app.release)
|
||||
* [Jsdelivr](https://cdn.jsdelivr.net/gh/gedoor/release@release/)
|
||||
* [\#Beta](https://kunfei.lanzoui.com/b0f810h4b)
|
||||
* [IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/io.legado.app.release)
|
||||
|
||||
|
||||
#### IOS
|
||||
|
||||
* Stopped(No release) - [Github](https://github.com/gedoor/YueDuFlutter)
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right">
|
||||
<img src="https://img.shields.io/badge/-Top-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
# Community [](#Community-)
|
||||
|
||||
#### Telegram
|
||||
[](https://t.me/yueduguanfang) [](https://t.me/legado_channels)
|
||||
|
||||
[](https://t.me/yueduguanfang) [](https://t.me/legado_channels)
|
||||
|
||||
#### Discord
|
||||
|
||||
[](https://discord.gg/VtUfRyzRXn)
|
||||
|
||||
#### Other
|
||||
|
||||
https://www.yuque.com/legado/wiki/community
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right">
|
||||
<img src="https://img.shields.io/badge/-Top-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
# API [](#API-)
|
||||
|
||||
* Legado 3.0 The API is provided in 2 ways: `Web way` and `Content Provider way`. You can call it yourself as needed in [here](api.md).
|
||||
* One-click import by url recall reading, url format: legado://import/{path}?src={url}
|
||||
* Path Type: bookSource,rssSource,replaceRule,textTocRule,httpTTS,theme,readConfig
|
||||
* path type explanation: Book source, subscription source, replacement rules, local txt novel directory rules, online reading engine, theme, reading layout
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right">
|
||||
<img src="https://img.shields.io/badge/-Top-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
# Other [](#Other-)
|
||||
|
||||
##### Disclaimers
|
||||
|
||||
https://gedoor.github.io/about.html
|
||||
|
||||
##### Legado 3.0
|
||||
|
||||
* [eBook sources rules](https://alanskycn.gitee.io/teachme)
|
||||
* [Update Log](/app/src/main/assets/updateLog.md)
|
||||
* [Help Documentation](/app/src/main/assets/help/appHelp.md)
|
||||
* [web](https://github.com/gedoor/legado_web_bookshelf)
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right">
|
||||
<img src="https://img.shields.io/badge/-Top-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
# Grateful [](#Grateful-)
|
||||
|
||||
> * org.jsoup:jsoup
|
||||
> * cn.wanghaomiao:JsoupXpath
|
||||
> * com.jayway.jsonpath:json-path
|
||||
@@ -123,14 +131,16 @@ https://gedoor.github.io/about.html
|
||||
> * io.noties.markwon:image-glide
|
||||
> * com.hankcs:hanlp
|
||||
> * com.positiondev.epublib:epublib-core
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right">
|
||||
<img src="https://img.shields.io/badge/-Top-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
# Interface [](#Interface-)
|
||||
|
||||
<img src="https://github.com/gedoor/gedoor.github.io/blob/master/static/img/legado/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B1.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/static/img/legado/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B2.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/static/img/legado/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B3.jpg" width="270">
|
||||
<img src="https://github.com/gedoor/gedoor.github.io/blob/master/static/img/legado/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B4.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/static/img/legado/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B5.jpg" width="270"><img src="https://github.com/gedoor/gedoor.github.io/blob/master/static/img/legado/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B6.jpg" width="270">
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="#" align="right">
|
||||
<img src="https://img.shields.io/badge/-Top-orange.svg" alt="#" align="right">
|
||||
</a>
|
||||
@@ -46,7 +46,6 @@ Legado is a free and open source novel reader for Android.
|
||||
* [Releases](https://github.com/gedoor/legado/releases/latest)
|
||||
* [Google play - $1.99](https://play.google.com/store/apps/details?id=io.legado.play.release)
|
||||
* [Coolapk](https://www.coolapk.com/apk/io.legado.app.release)
|
||||
* [Jsdelivr](https://cdn.jsdelivr.net/gh/gedoor/release@release/)
|
||||
* [\#Beta](https://kunfei.lanzoui.com/b0f810h4b)
|
||||
* [IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/io.legado.app.release)
|
||||
|
||||
|
||||
+3
-5
@@ -164,7 +164,7 @@ dependencies {
|
||||
implementation('androidx.constraintlayout:constraintlayout:2.1.4')
|
||||
implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0')
|
||||
implementation('androidx.viewpager2:viewpager2:1.0.0')
|
||||
implementation('androidx.webkit:webkit:1.4.0')
|
||||
implementation('androidx.webkit:webkit:1.5.0')
|
||||
|
||||
//google
|
||||
implementation('com.google.android.material:material:1.6.1')
|
||||
@@ -189,8 +189,6 @@ dependencies {
|
||||
|
||||
//media
|
||||
implementation("androidx.media:media:1.6.0")
|
||||
|
||||
|
||||
implementation("com.google.android.exoplayer:exoplayer-core:$exoplayer_version")
|
||||
implementation("com.google.android.exoplayer:extension-okhttp:$exoplayer_version")
|
||||
|
||||
@@ -209,7 +207,7 @@ dependencies {
|
||||
implementation('io.github.jeremyliao:live-event-bus-x:1.8.0')
|
||||
|
||||
//规则相关
|
||||
implementation('org.jsoup:jsoup:1.15.2')
|
||||
implementation('org.jsoup:jsoup:1.15.3')
|
||||
implementation('com.jayway.jsonpath:json-path:2.7.0')
|
||||
implementation('cn.wanghaomiao:JsoupXpath:2.5.1')
|
||||
implementation(project(path: ':epublib'))
|
||||
@@ -260,7 +258,7 @@ dependencies {
|
||||
//implementation 'com.google.firebase:firebase-analytics-ktx:21.0.0'
|
||||
//implementation 'com.google.firebase:firebase-perf-ktx:20.0.6'
|
||||
|
||||
// LeakCanary
|
||||
//LeakCanary, 内存泄露检测
|
||||
//debugImplementation('com.squareup.leakcanary:leakcanary-android:2.7')
|
||||
|
||||
//com.github.AmrDeveloper:CodeView代码编辑已集成到应用内
|
||||
|
||||
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天"
|
||||
}
|
||||
@@ -152,5 +152,4 @@ let options = {
|
||||
```
|
||||
|
||||
* 购买操作
|
||||
> 返回购买链接,可直接填写链接或者JavaScript
|
||||
> 可用变量 book chapter java(不支持AnalyzeRule函数) source
|
||||
> 可直接填写链接或者JavaScript,如果执行结果是字符串链接将会自动打开浏览器
|
||||
@@ -11,6 +11,39 @@
|
||||
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
||||
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
||||
|
||||
**2022/09/03**
|
||||
|
||||
* 更新cronet: 105.0.5195.77
|
||||
* 更新web端书源编辑 by jgckM
|
||||
|
||||
**2022/08/31**
|
||||
|
||||
* 更新cronet: 105.0.5195.68
|
||||
* 修复一些bug
|
||||
* 给书源点赞 by SJJ-dot
|
||||
* 墨水屏模式下,书籍信息页不显示模糊书籍封面作为背景
|
||||
|
||||
**2022/08/23**
|
||||
|
||||
* 验证码输入框显示来自哪个书源
|
||||
* 修复一键导入丢失url参数的问题
|
||||
|
||||
**2022/08/19**
|
||||
|
||||
* 更新cronet: 104.0.5112.97
|
||||
* 现在选择文本朗读会从选择处一直往下朗读,朗读更方便
|
||||
* 阅读界面的TXT目录正则 弹框中也支持正则标题示例
|
||||
* 一些优化 by 821938089
|
||||
* 优化epub封面加载,修复图片读取,修复目录索引问题
|
||||
* 本地内容获取时尝试HTML实体解码,优化报错提示和添加日志
|
||||
* 优化书源校验,注释Error行
|
||||
* 订阅源、书架管理添加选中所选区间
|
||||
* 优化订阅源分组显示已启用分组,订阅源管理增加已启用、已禁用、需要登录、未分组分组
|
||||
* 订阅源长按菜单添加禁用源、分组管理排序
|
||||
* 添加返回时提示放入书架设置
|
||||
* 优化备份设置子文件夹对话框内容显示和校验
|
||||
* 修复搜索手动停止滑到底又重新搜索
|
||||
|
||||
**2022/08/02**
|
||||
|
||||
* 更新cronet: 104.0.5112.69
|
||||
|
||||
@@ -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}
|
||||
Binary file not shown.
|
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,439 +1 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>阅读3.0源编辑器_V4.0</title>
|
||||
<link rel="icon" href="../favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="index.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="editor">
|
||||
<div class="setbox">
|
||||
<div>
|
||||
<a href="../index.html">←主页</a>
|
||||
<b>书源</b>
|
||||
</div>
|
||||
<div class="rules">
|
||||
<div><b>基本</b></div>
|
||||
<div>
|
||||
<div>源域名 :</div>
|
||||
<textarea rows="1" id="bookSourceUrl" class="base" title="bookSourceUrl"
|
||||
placeholder="<必填>通常填写网站主页,例: https://www.qidian.com"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>源类型 :</div>
|
||||
<textarea rows="1" id="bookSourceType" class="base" title="bookSourceType"
|
||||
placeholder="<必填>0:文本 1:音频 2:图片 3:文件(只提供下载的网站)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>源名称 :</div>
|
||||
<textarea rows="1" id="bookSourceName" class="base" title="bookSourceName"
|
||||
placeholder="<必填>会显示在源列表"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>源分组 :</div>
|
||||
<textarea rows="1" id="bookSourceGroup" class="base" title="bookSourceGroup"
|
||||
placeholder="<选填>描述源的特征信息"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>源注释 :</div>
|
||||
<textarea rows="1" id="bookSourceComment" class="base" title="bookSourceComment"
|
||||
placeholder="<选填>描述源作者和状态"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>登录地址:</div>
|
||||
<textarea rows="1" id="loginUrl" class="base" title="loginUrl"
|
||||
placeholder="<选填>填写网站登录网址,仅在需要登录的源有用"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>登录界面:</div>
|
||||
<textarea rows="3" id="loginUi" class="base" title="loginUi"
|
||||
placeholder="<选填>自定义登录界面"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>登录检测:</div>
|
||||
<textarea rows="3" id="loginCheckJs" class="base" title="loginCheckJs"
|
||||
placeholder="<选填>登录检测js"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>并发率 :</div>
|
||||
<textarea rows="1" id="concurrentRate" class="base" title="concurrentRate"
|
||||
placeholder="<选填>并发率"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>请求头 :</div>
|
||||
<textarea rows="3" id="header" class="base" title="header"
|
||||
placeholder="<选填>客户端标识"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>链接验证:</div>
|
||||
<textarea rows="1" id="bookUrlPattern" class="base" title="bookUrlPattern"
|
||||
placeholder="<选填>当详情页URL与源URL的域名不一致时有效,用于添加网址"></textarea>
|
||||
</div>
|
||||
<p></p>
|
||||
<div><b>搜索</b></div>
|
||||
<div>
|
||||
<div>搜索地址:</div>
|
||||
<textarea rows="1" id="searchUrl" class="base" title="searchUrl"
|
||||
placeholder="[域名可省略]/search.php@kw={{key}}"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>校验文字:</div>
|
||||
<textarea rows="1" id="ruleSearch_checkKeyWord" class="ruleSearch"
|
||||
title="checkKeyWord"
|
||||
placeholder="校验关键字"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>列表规则:</div>
|
||||
<textarea rows="1" id="ruleSearch_bookList" class="ruleSearch" title="bookList"
|
||||
placeholder="选择书籍节点 (规则结果为List<Element>)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>书名规则:</div>
|
||||
<textarea rows="1" id="ruleSearch_name" class="ruleSearch" title="name"
|
||||
placeholder="选择节点书名 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>作者规则:</div>
|
||||
<textarea rows="1" id="ruleSearch_author" class="ruleSearch" title="author"
|
||||
placeholder="选择节点作者 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>分类规则:</div>
|
||||
<textarea rows="1" id="ruleSearch_kind" class="ruleSearch" title="kind"
|
||||
placeholder="选择节点分类信息 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>字数规则:</div>
|
||||
<textarea rows="1" id="ruleSearch_wordCount" class="ruleSearch" title="wordCount"
|
||||
placeholder="选择节点字数信息 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>最新章节:</div>
|
||||
<textarea rows="1" id="ruleSearch_lastChapter" class="ruleSearch"
|
||||
title="lastChapter"
|
||||
placeholder="选择节点最新章节 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>简介规则:</div>
|
||||
<textarea rows="1" id="ruleSearch_intro" class="ruleSearch" title="intro"
|
||||
placeholder="选择节点书籍简介 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>封面规则:</div>
|
||||
<textarea rows="1" id="ruleSearch_coverUrl" class="ruleSearch" title="coverUrl"
|
||||
placeholder="选择节点书籍封面 (规则结果为String类型的url)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>详情地址:</div>
|
||||
<textarea rows="1" id="ruleSearch_bookUrl" class="ruleSearch" title="bookUrl"
|
||||
placeholder="选择书籍详情页网址 (规则结果为String类型的url)"></textarea>
|
||||
</div>
|
||||
<p></p>
|
||||
<div><b>发现</b></div>
|
||||
<div>
|
||||
<div>发现地址:</div>
|
||||
<textarea rows="6" id="exploreUrl" class="base" title="exploreUrl"
|
||||
placeholder="内容能显示在发现菜单 每行一条发现分类(网址域名可省略),例: 名称1::网址(Url)1 名称2::网址(Url)2 ..."></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>列表规则:</div>
|
||||
<textarea rows="1" id="ruleExplore_bookList" class="ruleExplore" title="bookList"
|
||||
placeholder="选择书籍节点 (规则结果为List<Element>)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>书名规则:</div>
|
||||
<textarea rows="1" id="ruleExplore_name" class="ruleExplore" title="name"
|
||||
placeholder="选择节点书名 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>作者规则:</div>
|
||||
<textarea rows="1" id="ruleExplore_author" class="ruleExplore" title="author"
|
||||
placeholder="选择节点作者 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>分类规则:</div>
|
||||
<textarea rows="1" id="ruleExplore_kind" class="ruleExplore" title="kind"
|
||||
placeholder="选择节点分类信息 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>字数规则:</div>
|
||||
<textarea rows="1" id="ruleExplore_wordCount" class="ruleExplore" title="wordCount"
|
||||
placeholder="选择节点字数信息 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>最新章节:</div>
|
||||
<textarea rows="1" id="ruleExplore_lastChapter" class="ruleExplore"
|
||||
title="lastChapter"
|
||||
placeholder="选择节点最新章节 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>简介规则:</div>
|
||||
<textarea rows="1" id="ruleExplore_intro" class="ruleExplore" title="intro"
|
||||
placeholder="选择节点书籍简介 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>封面规则:</div>
|
||||
<textarea rows="1" id="ruleExplore_coverUrl" class="ruleExplore" title="coverUrl"
|
||||
placeholder="选择节点书籍封面 (规则结果为String类型的url)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>详情地址:</div>
|
||||
<textarea rows="1" id="ruleExplore_bookUrl" class="ruleExplore" title="bookUrl"
|
||||
placeholder="选择书籍详情页网址 (规则结果为String类型的url)"></textarea>
|
||||
</div>
|
||||
<p></p>
|
||||
<div><b>详情</b></div>
|
||||
<div>
|
||||
<div>预处理 :</div>
|
||||
<textarea rows="3" id="ruleBookInfo_init" class="ruleBookInfo" title="init"
|
||||
placeholder="用于加速详情信息检索,只支持AllInOne规则"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>书名规则:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_name" class="ruleBookInfo" title="name"
|
||||
placeholder="选择节点书名 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>作者规则:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_author" class="ruleBookInfo" title="author"
|
||||
placeholder="选择节点作者 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>分类规则:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_kind" class="ruleBookInfo" title="kind"
|
||||
placeholder="选择节点分类信息 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>字数规则:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_wordCount" class="ruleBookInfo"
|
||||
title="wordCount"
|
||||
placeholder="选择节点字数信息 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>最新章节:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_lastChapter" class="ruleBookInfo"
|
||||
title="lastChapter"
|
||||
placeholder="选择节点最新章节 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>简介规则:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_intro" class="ruleBookInfo" title="intro"
|
||||
placeholder="选择节点书籍简介 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>封面规则:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_coverUrl" class="ruleBookInfo" title="coverUrl"
|
||||
placeholder="选择节点书籍封面 (规则结果为String类型的url)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>目录地址:</div>
|
||||
<textarea rows="1" id="ruleBookInfo_tocUrl" class="ruleBookInfo" title="tocUrl"
|
||||
placeholder="选择书籍详情页网址 (规则结果为String类型的url, 与详情页相同时可省略)"></textarea>
|
||||
</div>
|
||||
<p></p>
|
||||
<div><b>目录</b></div>
|
||||
<div>
|
||||
<div>列表规则:</div>
|
||||
<textarea rows="3" id="ruleToc_chapterList" class="ruleToc" title="chapterList"
|
||||
placeholder="选择目录列表的章节节点 (规则结果为List<Element>)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>章节名称:</div>
|
||||
<textarea rows="1" id="ruleToc_chapterName" class="ruleToc" title="chapterName"
|
||||
placeholder="选择章节名称 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>章节地址:</div>
|
||||
<textarea rows="1" id="ruleToc_chapterUrl" class="ruleToc" title="chapterUrl"
|
||||
placeholder="选择章节链接 (规则结果为String类型的Url)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>卷名标识:</div>
|
||||
<textarea rows="1" id="ruleToc_isVolume" class="ruleToc" title="isVolume"
|
||||
placeholder="章节名称是否是卷名 (规则结果为Bool)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>收费标识:</div>
|
||||
<textarea rows="1" id="ruleToc_isVip" class="ruleToc" title="isVip"
|
||||
placeholder="章节是否为VIP章节 (规则结果为Bool)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>购买标识:</div>
|
||||
<textarea rows="1" id="ruleToc_isPay" class="ruleToc" title="isPay"
|
||||
placeholder="章节是否为已购买 (规则结果为Bool)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>章节信息:</div>
|
||||
<textarea rows="1" id="ruleToc_updateTime" class="ruleToc" title="updateTime"
|
||||
placeholder="选择章节信息 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>翻页规则:</div>
|
||||
<textarea rows="1" id="ruleToc_nextTocUrl" class="ruleToc" title="nextTocUrl"
|
||||
placeholder="选择目录下一页链接 (规则结果为List<String>或String)"></textarea>
|
||||
</div>
|
||||
<p></p>
|
||||
<div><b>正文</b></div>
|
||||
<div>
|
||||
<div>脚本注入:</div>
|
||||
<textarea rows="3" id="ruleContent_webJs" class="ruleContent" title="webJs"
|
||||
placeholder="注入javascript,用于模拟鼠标点击等,必须有返回值,一般为String类型"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>正文规则:</div>
|
||||
<textarea rows="1" id="ruleContent_content" class="ruleContent" title="content"
|
||||
placeholder="选择正文内容 (规则结果为String)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>翻页规则:</div>
|
||||
<textarea rows="1" id="ruleContent_nextContentUrl" class="ruleContent"
|
||||
title="nextContentUrl"
|
||||
placeholder="选择下一分页(不是下一章)链接 (规则结果为String类型的Url)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>资源正则:</div>
|
||||
<textarea rows="1" id="ruleContent_sourceRegex" class="ruleContent"
|
||||
title="sourceRegex"
|
||||
placeholder="匹配资源的url特征,用于嗅探"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>替换规则:</div>
|
||||
<textarea rows="1" id="ruleContent_replaceRegex" class="ruleContent"
|
||||
title="replaceRegex"
|
||||
placeholder="多页内容合并后替换,用于正文净化"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>图片样式:</div>
|
||||
<textarea rows="1" id="ruleContent_imageStyle" class="ruleContent"
|
||||
title="imageStyle"
|
||||
placeholder="FULL:铺满 不填:默认样式"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>购买操作:</div>
|
||||
<textarea rows="1" id="ruleContent_payAction" class="ruleContent"
|
||||
title="payAction"
|
||||
placeholder="购买章节 返回链接或js"></textarea>
|
||||
</div>
|
||||
<p></p>
|
||||
<div><b>其它规则</b></div>
|
||||
<div>
|
||||
<div>启用搜索:</div>
|
||||
<textarea rows="1" id="enabled" class="base" title="enabled"
|
||||
placeholder="启用: true 关闭: false (可选,默认true)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>启用发现:</div>
|
||||
<textarea rows="1" id="enabledExplore" class="base" title="enabledExplore"
|
||||
placeholder="启用: true 关闭: false (可选,默认true)"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>搜索权重:</div>
|
||||
<textarea rows="1" id="weight" class="base" title="weight"
|
||||
placeholder="整数: 0~N (可选,默认0) | 数字越大越靠前"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div>排序编号:</div>
|
||||
<textarea rows="1" id="customOrder" class="base" title="customOrder"
|
||||
placeholder="整数: 0~N (可选,默认0) | 数字越小越靠前"></textarea>
|
||||
</div>
|
||||
<div style="display:none;">
|
||||
<div>更新时间:</div>
|
||||
<textarea rows="1" id="lastUpdateTime" class="base" title="lastUpdateTime"
|
||||
placeholder="毫秒级时间戳 (自动生成) | 请勿手动填写"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu">
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">⇈推送源</text>
|
||||
<rect id="push"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">⇊拉取源</text>
|
||||
<rect id="pull"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">⋘编辑源</text>
|
||||
<rect id="editor"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">⋙生成源</text>
|
||||
<rect id="conver"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">✗清空表单</text>
|
||||
<rect id="initial"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">↶撤销操作</text>
|
||||
<rect id="undo"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">↷重做操作</text>
|
||||
<rect id="redo"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">⇏调试源</text>
|
||||
<rect id="debug"></rect>
|
||||
</svg>
|
||||
<svg class="button">
|
||||
<text x="50%" y="55%">✓保存源</text>
|
||||
<rect id="accept"></rect>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="outbox">
|
||||
<div class="tabbox">
|
||||
<div class="tabtitle">
|
||||
<div name="编辑源" class="tab1 this">编辑源</div>
|
||||
<div name="调试源" class="tab2">调试源</div>
|
||||
<div name="源列表" class="tab3">源列表</div>
|
||||
<div name="帮助信息" class="tab4">帮助信息</div>
|
||||
</div>
|
||||
<div class="tabbody">
|
||||
<div class="tab1 this">
|
||||
<textarea class="context" id="RuleJsonString"
|
||||
placeholder="这里输出序列化的JSON数据,可直接导入'阅读'APP"></textarea>
|
||||
</div>
|
||||
<div class="tab2">
|
||||
<input type="text" class="inputbox" id="DebugKey" placeholder="输入搜索关键字,默认搜「我的」">
|
||||
<textarea class="context" id="DebugConsole" placeholder="这里用于输出调试信息"></textarea>
|
||||
</div>
|
||||
<div class="tab3">
|
||||
<input type="text" class="inputbox" id="Filter"
|
||||
placeholder="输入筛选关键词(源名称、源URL或源分组)后按回车筛选源">
|
||||
<div class="titlebar">
|
||||
<button id="Import">导入源文件</button>
|
||||
<button id="Export">导出源文件</button>
|
||||
<button id="Delete">删除选中源</button>
|
||||
<button id="ClrAll">清空列表</button>
|
||||
</div>
|
||||
<div class="context" id="RuleList"></div>
|
||||
</div>
|
||||
<div class="tab4">
|
||||
<div class="context link">
|
||||
<a target="_blank" href="https://alanskycn.gitee.io/teachme">源制作教程</a>
|
||||
<a target="_blank"
|
||||
href="https://zhuanlan.zhihu.com/p/29436838">Xpath基础教程</a>
|
||||
<a target="_blank"
|
||||
href="https://zhuanlan.zhihu.com/p/32187820">Xpath高级教程</a>
|
||||
<a target="_blank" href="https://www.w3cschool.cn/regex_rmjc">正则表达式教程</a>
|
||||
<a target="_blank" href="https://regexr.com">正则表达式在线验证工具</a>
|
||||
<div>^$()[]{}.?+*| 这些是Java正则特殊符号,匹配需转义
|
||||
<br>(?s) 前缀表示跨行解析
|
||||
<br>(?m) 前缀表示逐行匹配
|
||||
<br>(?i) 前缀表示忽略大小写
|
||||
</div>
|
||||
<a target="_blank" href="https://www.beta.browxy.com">代码在线运行工具</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="index.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="./favicon.ico"><title>legado_web_editor</title><script defer="defer" src="./js/chunk-vendors.86212f98.js"></script><script defer="defer" src="./js/app.836bd8bb.js"></script><link href="./css/app.37e72839.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but legado_web_editor doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
@@ -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:
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
(function(){"use strict";var t={800:function(t,e,o){var n=o(963),r=o(252);const a={class:"editor"};function i(t,e,o,n,i,l){const c=(0,r.up)("router-view");return(0,r.wg)(),(0,r.iD)("div",a,[(0,r.Wm)(c)])}var l={setup(){}},c=o(744);const s=(0,c.Z)(l,[["render",i]]);var u=s,d=o(201),h=o(577);const p=t=>((0,r.dD)("data-v-de4729c0"),t=t(),(0,r.Cn)(),t),g={class:"left"},m=p((()=>(0,r._)("div",null,[(0,r._)("a",{href:"/"},"←主页"),(0,r._)("b",null,"书源")],-1))),b=["onClick"],v=["onClick"],k=["onClick"],w=["onClick"],S=["onClick"],C=["onClick"],_=["onClick"];function f(t,e,o,n,a,i){const l=(0,r.up)("router-link"),c=(0,r.up)("router-view"),s=(0,r.up)("edit-menu"),u=(0,r.up)("edit-out");return(0,r.wg)(),(0,r.iD)(r.HY,null,[(0,r._)("div",g,[(0,r._)("div",null,[m,(0,r._)("ul",null,[(0,r.Wm)(l,{to:{name:"base"},custom:""},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 基础 ",10,b)])),_:1}),(0,r.Wm)(l,{to:{name:"search"},custom:""},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 搜索 ",10,v)])),_:1}),(0,r.Wm)(l,{to:{name:"find"},custom:""},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 发现 ",10,k)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"detail"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 详情 ",10,w)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"directory"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 目录 ",10,S)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"content"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 正文 ",10,C)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"other"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 其他 ",10,_)])),_:1})])]),(0,r.Wm)(c,null,{default:(0,r.w5)((({Component:t})=>[((0,r.wg)(),(0,r.j4)(r.Ob,null,[((0,r.wg)(),(0,r.j4)((0,r.LL)(t)))],1024))])),_:1})]),(0,r.Wm)(s),(0,r.Wm)(u)],64)}var y=o(262);const I=t=>((0,r.dD)("data-v-8302f478"),t=t(),(0,r.Cn)(),t),D={class:"menu"},U=(0,r.Uk)("⇈推送源 "),x=I((()=>(0,r._)("span",null,"Ctrl+P",-1))),T=[U,x],B=(0,r.Uk)("⇊拉取源 "),K=I((()=>(0,r._)("span",null,"Shift+P",-1))),A=[B,K],j=(0,r.Uk)("⋙生成源"),E=I((()=>(0,r._)("span",null,"Ctrl+E",-1))),H=[j,E],N=(0,r.Uk)(" ✗清空表单"),O=I((()=>(0,r._)("span",null,"Shift+C",-1))),L=[N,O],P=(0,r.Uk)("↶撤销操作"),J=I((()=>(0,r._)("span",null,"Ctrl+Z",-1))),Z=[P,J],q=(0,r.Uk)("↷重做操作"),W=I((()=>(0,r._)("span",null,"Shift+R",-1))),M=[q,W],$=(0,r.Uk)(" ⇏调试源 "),R=I((()=>(0,r._)("span",null,"Ctrl+Enter",-1))),Y=[$,R],z=(0,r.Uk)(" ✓保存源"),V=I((()=>(0,r._)("span",null,"Ctrl+S",-1))),F=[z,V];function G(t,e,o,n,a,i){const l=(0,r.up)("edit-loading"),c=(0,r.up)("edit-warn"),s=(0,r.up)("edit-success");return(0,r.wg)(),(0,r.iD)("div",D,[(0,r._)("div",null,[n.isShow?((0,r.wg)(),(0,r.j4)(l,{key:0})):(0,r.kq)("",!0),(0,r.Wm)(c,{text:n.warnText,"is-show":n.warnShow,onChangeShow:n.changeShow},null,8,["text","is-show","onChangeShow"]),n.successShow?((0,r.wg)(),(0,r.j4)(s,{key:1,isShow:n.successShow,onChangeShow:n.changeSuccessShow,text:n.successText},null,8,["isShow","onChangeShow","text"])):(0,r.kq)("",!0)]),(0,r._)("button",{onClick:e[0]||(e[0]=(...t)=>n.push&&n.push(...t)),title:"Ctrl+P"},T),(0,r._)("button",{onClick:e[1]||(e[1]=(...t)=>n.pull&&n.pull(...t)),title:"Shift+P"},A),(0,r._)("button",{onClick:e[2]||(e[2]=(...t)=>n.conver&&n.conver(...t)),title:"Ctrl+E"},H),(0,r._)("button",{onClick:e[3]||(e[3]=(...t)=>n.clearEdit&&n.clearEdit(...t)),title:"Shift+C"},L),(0,r._)("button",{onClick:e[4]||(e[4]=(...t)=>n.undo&&n.undo(...t)),title:"Ctrl+Z"},Z),(0,r._)("button",{onClick:e[5]||(e[5]=(...t)=>n.redo&&n.redo(...t)),title:"Shift+R"},M),(0,r._)("button",{onClick:e[6]||(e[6]=(...t)=>n.debug&&n.debug(...t)),title:"Ctrl+Enter"},Y),(0,r._)("button",{onClick:e[7]||(e[7]=(...t)=>n.saveSource&&n.saveSource(...t)),title:"Ctrl+S"},F)])}function Q(t,e){let o;switch(o=null===localStorage.getItem("url")?"http://"+location.host+"/"+t:"http://"+localStorage.getItem("url")+"/"+t,console.log(o),t){case"getBookSources":return tt(o);case"saveBookSources":return X(o,e);case"deleteBookSources":return X(o,e)}}function X(t,e){return fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).then((t=>t.json()))}function tt(t){return fetch(t).then((t=>t.json()))}var et=o(907),ot=JSON.parse('{"bookSourceUrl":"","bookSourceType":"","bookSourceName":"","bookSourceGroup":"","bookSourceComment":"","loginUrl":"","loginUi":"","loginCheckJs":"","concurrentRate":"","header":"","bookUrlPattern":"","searchUrl":"","exploreUrl":"","enabled":true,"enabledExplore":true,"weight":null,"customOrder":null,"lastUpdLine truncated
|
||||
//# sourceMappingURL=app.2c3e42a8.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"js/app.2c3e42a8.js","mappings":"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 truncated
|
||||
@@ -0,0 +1,2 @@
|
||||
(function(){"use strict";var t={27:function(t,e,o){var n=o(963),r=o(252);const a={class:"editor"};function i(t,e,o,n,i,l){const c=(0,r.up)("router-view");return(0,r.wg)(),(0,r.iD)("div",a,[(0,r.Wm)(c)])}var l={setup(){}},c=o(744);const s=(0,c.Z)(l,[["render",i]]);var u=s,d=o(201),h=o(577);const p=t=>((0,r.dD)("data-v-de4729c0"),t=t(),(0,r.Cn)(),t),g={class:"left"},m=p((()=>(0,r._)("div",null,[(0,r._)("a",{href:"/"},"←主页"),(0,r._)("b",null,"书源")],-1))),b=["onClick"],v=["onClick"],k=["onClick"],w=["onClick"],S=["onClick"],C=["onClick"],_=["onClick"];function f(t,e,o,n,a,i){const l=(0,r.up)("router-link"),c=(0,r.up)("router-view"),s=(0,r.up)("edit-menu"),u=(0,r.up)("edit-out");return(0,r.wg)(),(0,r.iD)(r.HY,null,[(0,r._)("div",g,[(0,r._)("div",null,[m,(0,r._)("ul",null,[(0,r.Wm)(l,{to:{name:"base"},custom:""},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 基础 ",10,b)])),_:1}),(0,r.Wm)(l,{to:{name:"search"},custom:""},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 搜索 ",10,v)])),_:1}),(0,r.Wm)(l,{to:{name:"find"},custom:""},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 发现 ",10,k)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"detail"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 详情 ",10,w)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"directory"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 目录 ",10,S)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"content"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 正文 ",10,C)])),_:1}),(0,r.Wm)(l,{custom:"",to:{name:"other"}},{default:(0,r.w5)((({navigate:t,isActive:e})=>[(0,r._)("li",{onClick:t,class:(0,h.C_)({active:e?"active":""})}," 其他 ",10,_)])),_:1})])]),(0,r.Wm)(c,null,{default:(0,r.w5)((({Component:t})=>[((0,r.wg)(),(0,r.j4)(r.Ob,null,[((0,r.wg)(),(0,r.j4)((0,r.LL)(t)))],1024))])),_:1})]),(0,r.Wm)(s),(0,r.Wm)(u)],64)}var y=o(262);const I=t=>((0,r.dD)("data-v-7d09e592"),t=t(),(0,r.Cn)(),t),D={class:"menu"},U=(0,r.Uk)("⇈推送源 "),x=I((()=>(0,r._)("span",null,"Ctrl+P",-1))),T=[U,x],B=(0,r.Uk)("⇊拉取源 "),K=I((()=>(0,r._)("span",null,"Shift+P",-1))),A=[B,K],j=(0,r.Uk)("⋙生成源"),E=I((()=>(0,r._)("span",null,"Ctrl+E",-1))),H=[j,E],N=(0,r.Uk)(" ✗清空表单"),O=I((()=>(0,r._)("span",null,"Shift+C",-1))),L=[N,O],P=(0,r.Uk)("↶撤销操作"),J=I((()=>(0,r._)("span",null,"Ctrl+Z",-1))),Z=[P,J],q=(0,r.Uk)("↷重做操作"),W=I((()=>(0,r._)("span",null,"Shift+R",-1))),M=[q,W],$=(0,r.Uk)(" ⇏调试源 "),R=I((()=>(0,r._)("span",null,"Ctrl+Enter",-1))),Y=[$,R],z=(0,r.Uk)(" ✓保存源"),V=I((()=>(0,r._)("span",null,"Ctrl+S",-1))),F=[z,V];function G(t,e,o,n,a,i){const l=(0,r.up)("edit-loading"),c=(0,r.up)("edit-warn"),s=(0,r.up)("edit-success");return(0,r.wg)(),(0,r.iD)("div",D,[(0,r._)("div",null,[n.isShow?((0,r.wg)(),(0,r.j4)(l,{key:0})):(0,r.kq)("",!0),(0,r.Wm)(c,{text:n.warnText,"is-show":n.warnShow,onChangeShow:n.changeShow},null,8,["text","is-show","onChangeShow"]),n.successShow?((0,r.wg)(),(0,r.j4)(s,{key:1,isShow:n.successShow,onChangeShow:n.changeSuccessShow,text:n.successText},null,8,["isShow","onChangeShow","text"])):(0,r.kq)("",!0)]),(0,r._)("button",{onClick:e[0]||(e[0]=(...t)=>n.push&&n.push(...t)),title:"Ctrl+P"},T),(0,r._)("button",{onClick:e[1]||(e[1]=(...t)=>n.pull&&n.pull(...t)),title:"Shift+P"},A),(0,r._)("button",{onClick:e[2]||(e[2]=(...t)=>n.conver&&n.conver(...t)),title:"Ctrl+E"},H),(0,r._)("button",{onClick:e[3]||(e[3]=(...t)=>n.clearEdit&&n.clearEdit(...t)),title:"Shift+C"},L),(0,r._)("button",{onClick:e[4]||(e[4]=(...t)=>n.undo&&n.undo(...t)),title:"Ctrl+Z"},Z),(0,r._)("button",{onClick:e[5]||(e[5]=(...t)=>n.redo&&n.redo(...t)),title:"Shift+R"},M),(0,r._)("button",{onClick:e[6]||(e[6]=(...t)=>n.debug&&n.debug(...t)),title:"Ctrl+Enter"},Y),(0,r._)("button",{onClick:e[7]||(e[7]=(...t)=>n.saveSource&&n.saveSource(...t)),title:"Ctrl+S"},F)])}function Q(t,e){let o;switch(o=null===localStorage.getItem("url")?"http://"+location.host+"/"+t:"http://"+localStorage.getItem("url")+"/"+t,console.log(o),t){case"getBookSources":return tt(o);case"saveBookSources":return X(o,e);case"deleteBookSources":return X(o,e)}}function X(t,e){return fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).then((t=>t.json()))}function tt(t){return fetch(t).then((t=>t.json()))}var et=o(907),ot=JSON.parse('{"bookSourceUrl":"","bookSourceType":"","bookSourceName":"","bookSourceGroup":"","bookSourceComment":"","loginUrl":"","loginUi":"","loginCheckJs":"","concurrentRate":"","header":"","bookUrlPattern":"","searchUrl":"","exploreUrl":"","enabled":true,"enabledExplore":true,"weight":null,"customOrder":null,"lastUpdaLine truncated
|
||||
//# sourceMappingURL=app.836bd8bb.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"js/app.836bd8bb.js","mappings":"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 truncated
|
||||
@@ -0,0 +1,14 @@
|
||||
"use strict";(self["webpackChunklegado_web_editor"]=self["webpackChunklegado_web_editor"]||[]).push([[998],{262:function(e,t,n){n.d(t,{BK:function(){return De},Bj:function(){return s},Fl:function(){return He},IU:function(){return Re},Jd:function(){return x},PG:function(){return Ce},SU:function(){return Ne},Um:function(){return we},WL:function(){return Ve},X$:function(){return O},X3:function(){return Oe},XI:function(){return Le},Xl:function(){return Ae},dq:function(){return Fe},iH:function(){return Me},j:function(){return S},lk:function(){return C},qj:function(){return be},qq:function(){return _},yT:function(){return Ee}});var r=n(577);let o;class s{constructor(e=!1){this.active=!0,this.effects=[],this.cleanups=[],!e&&o&&(this.parent=o,this.index=(o.scopes||(o.scopes=[])).push(this)-1)}run(e){if(this.active){const t=o;try{return o=this,e()}finally{o=t}}else 0}on(){o=this}off(){o=this.parent}stop(e){if(this.active){let t,n;for(t=0,n=this.effects.length;t<n;t++)this.effects[t].stop();for(t=0,n=this.cleanups.length;t<n;t++)this.cleanups[t]();if(this.scopes)for(t=0,n=this.scopes.length;t<n;t++)this.scopes[t].stop(!0);if(this.parent&&!e){const e=this.parent.scopes.pop();e&&e!==this&&(this.parent.scopes[this.index]=e,e.index=this.index)}this.active=!1}}}function i(e,t=o){t&&t.active&&t.effects.push(e)}const c=e=>{const t=new Set(e);return t.w=0,t.n=0,t},l=e=>(e.w&h)>0,u=e=>(e.n&h)>0,a=({deps:e})=>{if(e.length)for(let t=0;t<e.length;t++)e[t].w|=h},f=e=>{const{deps:t}=e;if(t.length){let n=0;for(let r=0;r<t.length;r++){const o=t[r];l(o)&&!u(o)?o.delete(e):t[n++]=o,o.w&=~h,o.n&=~h}t.length=n}},p=new WeakMap;let d=0,h=1;const m=30;let g;const v=Symbol(""),y=Symbol("");class _{constructor(e,t=null,n){this.fn=e,this.scheduler=t,this.active=!0,this.deps=[],this.parent=void 0,i(this,n)}run(){if(!this.active)return this.fn();let e=g,t=w;while(e){if(e===this)return;e=e.parent}try{return this.parent=g,g=this,w=!0,h=1<<++d,d<=m?a(this):b(this),this.fn()}finally{d<=m&&f(this),h=1<<--d,g=this.parent,w=t,this.parent=void 0,this.deferStop&&this.stop()}}stop(){g===this?this.deferStop=!0:this.active&&(b(this),this.onStop&&this.onStop(),this.active=!1)}}function b(e){const{deps:t}=e;if(t.length){for(let n=0;n<t.length;n++)t[n].delete(e);t.length=0}}let w=!0;const k=[];function x(){k.push(w),w=!1}function C(){const e=k.pop();w=void 0===e||e}function S(e,t,n){if(w&&g){let t=p.get(e);t||p.set(e,t=new Map);let r=t.get(n);r||t.set(n,r=c());const o=void 0;E(r,o)}}function E(e,t){let n=!1;d<=m?u(e)||(e.n|=h,n=!l(e)):n=!e.has(g),n&&(e.add(g),g.deps.push(e))}function O(e,t,n,o,s,i){const l=p.get(e);if(!l)return;let u=[];if("clear"===t)u=[...l.values()];else if("length"===n&&(0,r.kJ)(e))l.forEach(((e,t)=>{("length"===t||t>=o)&&u.push(e)}));else switch(void 0!==n&&u.push(l.get(n)),t){case"add":(0,r.kJ)(e)?(0,r.S0)(n)&&u.push(l.get("length")):(u.push(l.get(v)),(0,r._N)(e)&&u.push(l.get(y)));break;case"delete":(0,r.kJ)(e)||(u.push(l.get(v)),(0,r._N)(e)&&u.push(l.get(y)));break;case"set":(0,r._N)(e)&&u.push(l.get(v));break}if(1===u.length)u[0]&&R(u[0]);else{const e=[];for(const t of u)t&&e.push(...t);R(c(e))}}function R(e,t){const n=(0,r.kJ)(e)?e:[...e];for(const r of n)r.computed&&A(r,t);for(const r of n)r.computed||A(r,t)}function A(e,t){(e!==g||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}const j=(0,r.fY)("__proto__,__v_isRef,__isVue"),I=new Set(Object.getOwnPropertyNames(Symbol).filter((e=>"arguments"!==e&&"caller"!==e)).map((e=>Symbol[e])).filter(r.yk)),T=$(),P=$(!1,!0),F=$(!0),M=L();function L(){const e={};return["includes","indexOf","lastIndexOf"].forEach((t=>{e[t]=function(...e){const n=Re(this);for(let t=0,o=this.length;t<o;t++)S(n,"get",t+"");const r=n[t](...e);return-1===r||!1===r?n[t](...e.map(Re)):r}})),["push","pop","shift","unshift","splice"].forEach((t=>{e[t]=function(...e){x();const n=Re(this)[t].apply(this,e);return C(),n}})),e}function $(e=!1,t=!1){return function(n,o,s){if("__v_isReactive"===o)return!e;if("__v_isReadonly"===o)return e;if("__v_isShallow"===o)return t;if("__v_raw"===o&&s===(e?t?ve:ge:t?me:he).get(n))return n;const i=(0,r.kJ)(n);if(!e&&i&&(0,r.RI)(M,o))return Reflect.get(M,o,s);const c=Reflect.get(n,o,s);return((0,r.yk)(o)?I.has(o):j(o))?c:(e||S(n,"get",o),t?c:Fe(c)?i&&(0,r.S0)(o)?c:c.value:(0,r.Kn)(c)?e?ke(c):be(c):c)}}const U=J(),N=J(!0);function J(e=!1){return function(t,n,o,s){let i=t[n];if(Se(i)&&Fe(i)&&!Fe(o))return!1;if(!e&&!Se(o)&&(Ee(o)||(o=Re(o),i=Re(i)),!(0,r.kJ)(t)&&Fe(i)&&!Fe(o)))return i.value=o,!0;const c=(0,r.kJ)(t)&&(0,r.S0)(n)?Number(n)<t.length:(0,r.RI)(t,n),l=Reflect.set(t,n,o,s);return t===Re(s)&&(c?(0,r.aU)(o,i)&&O(t,"set",n,o,i):O(t,"add",n,o)),l}}function V(e,t){const n=(0,r.RI)(e,t),o=e[t],s=Reflect.deleteProperty(e,t);return s&&n&&O(e,"delete",t,void 0,o),s}function D(e,t){const n=Reflect.has(e,t);return(0,r.yk)(t)&&I.has(t)||S(e,"has",t),n}function G(e){return S(e,"iterate",(0,r.kJ)(e)?"length":v),Reflect.ownKeys(e)}const B={get:T,set:U,deleteProperty:V,has:D,ownKeys:G},q={get:FLine truncated
|
||||
/*!
|
||||
* vuex v4.0.2
|
||||
* (c) 2021 Evan You
|
||||
* @license MIT
|
||||
*/
|
||||
var g="store";function v(e,t){Object.keys(e).forEach((function(n){return t(e[n],n)}))}function y(e){return null!==e&&"object"===typeof e}function _(e){return e&&"function"===typeof e.then}function b(e,t){return function(){return e(t)}}function w(e,t,n){return t.indexOf(e)<0&&(n&&n.prepend?t.unshift(e):t.push(e)),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}function k(e,t){e._actions=Object.create(null),e._mutations=Object.create(null),e._wrappedGetters=Object.create(null),e._modulesNamespaceMap=Object.create(null);var n=e.state;C(e,n,[],e._modules.root,!0),x(e,n,t)}function x(e,t,n){var r=e._state;e.getters={},e._makeLocalGettersCache=Object.create(null);var s=e._wrappedGetters,i={};v(s,(function(t,n){i[n]=b(t,e),Object.defineProperty(e.getters,n,{get:function(){return i[n]()},enumerable:!0})})),e._state=(0,o.qj)({data:t}),e.strict&&j(e),r&&n&&e._withCommit((function(){r.data=null}))}function C(e,t,n,r,o){var s=!n.length,i=e._modules.getNamespace(n);if(r.namespaced&&(e._modulesNamespaceMap[i],e._modulesNamespaceMap[i]=r),!s&&!o){var c=I(t,n.slice(0,-1)),l=n[n.length-1];e._withCommit((function(){c[l]=r.state}))}var u=r.context=S(e,i,n);r.forEachMutation((function(t,n){var r=i+n;O(e,r,t,u)})),r.forEachAction((function(t,n){var r=t.root?n:i+n,o=t.handler||t;R(e,r,o,u)})),r.forEachGetter((function(t,n){var r=i+n;A(e,r,t,u)})),r.forEachChild((function(r,s){C(e,t,n.concat(s),r,o)}))}function S(e,t,n){var r=""===t,o={dispatch:r?e.dispatch:function(n,r,o){var s=T(n,r,o),i=s.payload,c=s.options,l=s.type;return c&&c.root||(l=t+l),e.dispatch(l,i)},commit:r?e.commit:function(n,r,o){var s=T(n,r,o),i=s.payload,c=s.options,l=s.type;c&&c.root||(l=t+l),e.commit(l,i,c)}};return Object.defineProperties(o,{getters:{get:r?function(){return e.getters}:function(){return E(e,t)}},state:{get:function(){return I(e.state,n)}}}),o}function E(e,t){if(!e._makeLocalGettersCache[t]){var n={},r=t.length;Object.keys(e.getters).forEach((function(o){if(o.slice(0,r)===t){var s=o.slice(r);Object.defineProperty(n,s,{get:function(){return e.getters[o]},enumerable:!0})}})),e._makeLocalGettersCache[t]=n}return e._makeLocalGettersCache[t]}function O(e,t,n,r){var o=e._mutations[t]||(e._mutations[t]=[]);o.push((function(t){n.call(e,r.state,t)}))}function R(e,t,n,r){var o=e._actions[t]||(e._actions[t]=[]);o.push((function(t){var o=n.call(e,{dispatch:r.dispatch,commit:r.commit,getters:r.getters,state:r.state,rootGetters:e.getters,rootState:e.state},t);return _(o)||(o=Promise.resolve(o)),e._devtoolHook?o.catch((function(t){throw e._devtoolHook.emit("vuex:error",t),t})):o}))}function A(e,t,n,r){e._wrappedGetters[t]||(e._wrappedGetters[t]=function(e){return n(r.state,r.getters,e.state,e.getters)})}function j(e){(0,r.YP)((function(){return e._state.data}),(function(){0}),{deep:!0,flush:"sync"})}function I(e,t){return t.reduce((function(e,t){return e[t]}),e)}function T(e,t,n){return y(e)&&e.type&&(n=t,t=e,e=e.type),{type:e,payload:t,options:n}}var P="vuex bindings",F="vuex:mutations",M="vuex:actions",L="vuex",$=0;function U(e,t){m({id:"org.vuejs.vuex",app:e,label:"Vuex",homepage:"https://next.vuex.vuejs.org/",logo:"https://vuejs.org/images/icons/favicon-96x96.png",packageName:"vuex",componentStateTypes:[P]},(function(n){n.addTimelineLayer({id:F,label:"Vuex Mutations",color:N}),n.addTimelineLayer({id:M,label:"Vuex Actions",color:N}),n.addInspector({id:L,label:"Vuex",icon:"storage",treeFilterPlaceholder:"Filter stores..."}),n.on.getInspectorTree((function(n){if(n.app===e&&n.inspectorId===L)if(n.filter){var r=[];q(r,t._modules.root,n.filter,""),n.rootNodes=r}else n.rootNodes=[B(t._modules.root,"")]})),n.on.getInspectorState((function(n){if(n.app===e&&n.inspectorId===L){var r=n.nodeId;E(t,r),n.state=H(K(t._modules,r),"root"===r?t.getters:t._makeLocalGettersCache,r)}})),n.on.editInspectorState((function(n){if(n.app===e&&n.inspectorId===L){var r=n.nodeId,o=n.path;"root"!==r&&(o=r.split("/").filter(Boolean).concat(o)),t._withCommit((function(){n.set(t._state.data,o,n.state.value)}))}})),t.subscribe((function(e,t){var r={};e.payload&&(r.payload=e.payload),r.state=t,n.notifyComponentUpdate(),n.sendInspectorTree(L),n.sendInspectorState(L),n.addTimelineEvent({layerId:F,event:{time:Date.now(),title:e.type,data:r}})})),t.subscribeAction({before:function(e,t){var r={};e.payload&&(r.payload=e.payload),e._id=$++,e._time=Date.now(),r.state=t,n.addTimelineEvent({layerId:M,event:{time:e._time,title:e.type,groupId:e._id,subtitle:"start",data:r}})},after:function(e,t){var r={},o=Date.now()-e._time;r.duration={_custom:{type:"duration",display:o+"ms",tooltip:"Action duration",value:o}},e.payload&&(r.payload=e.payload),r.state=t,n.addTimelineEvent({layerId:M,event:{time:Date.now(),title:e.type,groupId:e._id,subtitle:"end",data:r}})}})}))}var N=8702998,J=6710886,V=16777215,D={label:"namespaced",textColor:V,backgroundColor:J};function G(e){return e&&"root"!==e?e.split("/").slice(-2,-1)[0]:"Root"}function B(e,t){return{id:t||"root",label:G(t),tags:e.namespaced?[D]:[],children:OLine truncated
|
||||
/*!
|
||||
* vue-router v4.1.4
|
||||
* (c) 2022 Eduardo San Martin Morote
|
||||
* @license MIT
|
||||
*/
|
||||
const s="undefined"!==typeof window;function i(e){return e.__esModule||"Module"===e[Symbol.toStringTag]}const c=Object.assign;function l(e,t){const n={};for(const r in t){const o=t[r];n[r]=a(o)?o.map(e):e(o)}return n}const u=()=>{},a=Array.isArray;const f=/\/$/,p=e=>e.replace(f,"");function d(e,t,n="/"){let r,o={},s="",i="";const c=t.indexOf("#");let l=t.indexOf("?");return c<l&&c>=0&&(l=-1),l>-1&&(r=t.slice(0,l),s=t.slice(l+1,c>-1?c:t.length),o=e(s)),c>-1&&(r=r||t.slice(0,c),i=t.slice(c,t.length)),r=w(null!=r?r:t,n),{fullPath:r+(s&&"?")+s+i,path:r,query:o,hash:i}}function h(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function m(e,t){return t&&e.toLowerCase().startsWith(t.toLowerCase())?e.slice(t.length)||"/":e}function g(e,t,n){const r=t.matched.length-1,o=n.matched.length-1;return r>-1&&r===o&&v(t.matched[r],n.matched[o])&&y(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function v(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function y(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!_(e[n],t[n]))return!1;return!0}function _(e,t){return a(e)?b(e,t):a(t)?b(t,e):e===t}function b(e,t){return a(t)?e.length===t.length&&e.every(((e,n)=>e===t[n])):1===e.length&&e[0]===t}function w(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/");let o,s,i=n.length-1;for(o=0;o<r.length;o++)if(s=r[o],"."!==s){if(".."!==s)break;i>1&&i--}return n.slice(0,i).join("/")+"/"+r.slice(o-(o===r.length?1:0)).join("/")}var k,x;(function(e){e["pop"]="pop",e["push"]="push"})(k||(k={})),function(e){e["back"]="back",e["forward"]="forward",e["unknown"]=""}(x||(x={}));function C(e){if(!e)if(s){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return"/"!==e[0]&&"#"!==e[0]&&(e="/"+e),p(e)}const S=/^[^#]+#/;function E(e,t){return e.replace(S,"#")+t}function O(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const R=()=>({left:window.pageXOffset,top:window.pageYOffset});function A(e){let t;if("el"in e){const n=e.el,r="string"===typeof n&&n.startsWith("#");0;const o="string"===typeof n?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=O(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(null!=t.left?t.left:window.pageXOffset,null!=t.top?t.top:window.pageYOffset)}function j(e,t){const n=history.state?history.state.position-t:-1;return n+e}const I=new Map;function T(e,t){I.set(e,t)}function P(e){const t=I.get(e);return I.delete(e),t}let F=()=>location.protocol+"//"+location.host;function M(e,t){const{pathname:n,search:r,hash:o}=t,s=e.indexOf("#");if(s>-1){let t=o.includes(e.slice(s))?e.slice(s).length:1,n=o.slice(t);return"/"!==n[0]&&(n="/"+n),m(n,"")}const i=m(n,e);return i+r+o}function L(e,t,n,r){let o=[],s=[],i=null;const l=({state:s})=>{const c=M(e,location),l=n.value,u=t.value;let a=0;if(s){if(n.value=c,t.value=s,i&&i===l)return void(i=null);a=u?s.position-u.position:0}else r(c);o.forEach((e=>{e(n.value,l,{delta:a,type:k.pop,direction:a?a>0?x.forward:x.back:x.unknown})}))};function u(){i=n.value}function a(e){o.push(e);const t=()=>{const t=o.indexOf(e);t>-1&&o.splice(t,1)};return s.push(t),t}function f(){const{history:e}=window;e.state&&e.replaceState(c({},e.state,{scroll:R()}),"")}function p(){for(const e of s)e();s=[],window.removeEventListener("popstate",l),window.removeEventListener("beforeunload",f)}return window.addEventListener("popstate",l),window.addEventListener("beforeunload",f),{pauseListeners:u,listen:a,destroy:p}}function $(e,t,n,r=!1,o=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:o?R():null}}function U(e){const{history:t,location:n}=window,r={value:M(e,n)},o={value:t.state};function s(r,s,i){const c=e.indexOf("#"),l=c>-1?(n.host&&document.querySelector("base")?e:e.slice(c))+r:F()+e+r;try{t[i?"replaceState":"pushState"](s,"",l),o.value=s}catch(u){console.error(u),n[i?"replace":"assign"](l)}}function i(e,n){const i=c({},t.state,$(o.value.back,e,o.value.forward,!0),n,{position:o.value.position});s(e,i,!0),r.value=e}function l(e,n){const i=c({},o.value,t.state,{forward:e,scroll:R()});s(i.current,i,!0);const l=c({},$(r.value,e,null),{position:i.position+1},n);s(e,l,!1),r.value=e}return o.value||s(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0),{location:r,state:o,push:l,replace:i}}function N(e){e=C(e);const t=U(e),n=L(e,t.state,t.location,t.replace);function r(e,t=!0){t||n.pauseListeners(),history.go(e)}const o=c({location:"",base:e,go:r,createHref:E.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function J(e){return e=location.host?e||locatioLine truncated
|
||||
//# sourceMappingURL=chunk-vendors.86212f98.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"js/chunk-vendors.86212f98.js","mappings":"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 truncated
|
||||
@@ -180,7 +180,7 @@ object BookController {
|
||||
?: return returnData.setErrorMsg("未找到书源")
|
||||
try {
|
||||
content = runBlocking {
|
||||
WebBook.getContentAwait(this, bookSource, book, chapter).let {
|
||||
WebBook.getContentAwait(bookSource, book, chapter).let {
|
||||
val contentProcessor = ContentProcessor.get(book.name, book.origin)
|
||||
contentProcessor.getContent(book, chapter, it, includeTitle = false)
|
||||
.joinToString("\n")
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.text.TextUtils
|
||||
import io.legado.app.api.ReturnData
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.BookSource
|
||||
import io.legado.app.help.config.SourceConfig
|
||||
import io.legado.app.utils.GSON
|
||||
import io.legado.app.utils.fromJsonArray
|
||||
|
||||
@@ -70,6 +71,7 @@ object BookSourceController {
|
||||
GSON.fromJsonArray<BookSource>(postData).getOrThrow()?.let {
|
||||
it.forEach { source ->
|
||||
appDb.bookSourceDao.delete(source)
|
||||
SourceConfig.removeSource(source.bookSourceUrl)
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
|
||||
@@ -109,6 +109,7 @@ object PreferKey {
|
||||
const val welcomeShowIcon = "welcomeShowIcon"
|
||||
const val welcomeShowIconDark = "welcomeShowIconDark"
|
||||
const val pageTouchSlop = "pageTouchSlop"
|
||||
const val showAddToShelfAlert = "showAddToShelfAlert"
|
||||
|
||||
const val cPrimary = "colorPrimary"
|
||||
const val cAccent = "colorAccent"
|
||||
|
||||
@@ -44,6 +44,15 @@ interface RssSourceDao {
|
||||
@Query("SELECT * FROM rssSources where enabled = 1 order by customOrder")
|
||||
fun flowEnabled(): Flow<List<RssSource>>
|
||||
|
||||
@Query("SELECT * FROM rssSources where enabled = 0 order by customOrder")
|
||||
fun flowDisabled(): Flow<List<RssSource>>
|
||||
|
||||
@Query("select * from rssSources where loginUrl is not null and loginUrl != ''")
|
||||
fun flowLogin(): Flow<List<RssSource>>
|
||||
|
||||
@Query("select * from rssSources where sourceGroup is null or sourceGroup = '' or sourceGroup like '%未分组%'")
|
||||
fun flowNoGroup(): Flow<List<RssSource>>
|
||||
|
||||
@Query(
|
||||
"""SELECT * FROM rssSources
|
||||
where enabled = 1
|
||||
@@ -67,6 +76,9 @@ interface RssSourceDao {
|
||||
@Query("select distinct sourceGroup from rssSources where trim(sourceGroup) <> ''")
|
||||
fun flowGroup(): Flow<List<String>>
|
||||
|
||||
@Query("select distinct sourceGroup from rssSources where trim(sourceGroup) <> '' and enabled = 1")
|
||||
fun flowGroupEnabled(): Flow<List<String>>
|
||||
|
||||
@get:Query("select distinct sourceGroup from rssSources where trim(sourceGroup) <> ''")
|
||||
val allGroup: List<String>
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ object SourceAnalyzer {
|
||||
}
|
||||
source.loginCheckJs = sourceAny.loginCheckJs
|
||||
source.bookSourceComment = sourceAny.bookSourceComment
|
||||
source.variableComment = sourceAny.variableComment
|
||||
source.lastUpdateTime = sourceAny.lastUpdateTime
|
||||
source.respondTime = sourceAny.respondTime
|
||||
source.weight = sourceAny.weight
|
||||
@@ -220,13 +221,14 @@ object SourceAnalyzer {
|
||||
var customOrder: Int = 0, // 手动排序编号
|
||||
var enabled: Boolean = true, // 是否启用
|
||||
var enabledExplore: Boolean = true, // 启用发现
|
||||
var enabledCookieJar: Boolean = false, // 启用CookieJar
|
||||
var enabledCookieJar: Boolean = false, // 启用CookieJar
|
||||
var concurrentRate: String? = null, // 并发率
|
||||
var header: String? = null, // 请求头
|
||||
var loginUrl: Any? = null, // 登录规则
|
||||
var loginUi: Any? = null, // 登录UI
|
||||
var loginCheckJs: String? = null, //登录检测js
|
||||
var bookSourceComment: String? = "", //书源注释
|
||||
var loginCheckJs: String? = null, // 登录检测js
|
||||
var bookSourceComment: String? = "", // 书源注释
|
||||
var variableComment: String? = null, // 变量说明
|
||||
var lastUpdateTime: Long = 0, // 最后更新时间,用于排序
|
||||
var respondTime: Long = 180000L, // 响应时间,用于排序
|
||||
var weight: Int = 0, // 智能排序的权重
|
||||
|
||||
@@ -27,6 +27,7 @@ object SourceVerificationHelp {
|
||||
appCtx.startActivity<VerificationCodeActivity> {
|
||||
putExtra("imageUrl", url)
|
||||
putExtra("sourceOrigin", source.getKey())
|
||||
putExtra("sourceName", source.getTag())
|
||||
}
|
||||
} else {
|
||||
startBrowser(source, url, title, true)
|
||||
@@ -58,6 +59,7 @@ object SourceVerificationHelp {
|
||||
putExtra("title", title)
|
||||
putExtra("url", url)
|
||||
putExtra("sourceOrigin", source.getKey())
|
||||
putExtra("sourceName", source.getTag())
|
||||
putExtra("sourceVerificationEnable", saveResult)
|
||||
IntentData.put(url, source.getHeaderMap(true))
|
||||
}
|
||||
|
||||
@@ -310,7 +310,9 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
val recordLog get() = appCtx.getPrefBoolean(PreferKey.recordLog)
|
||||
|
||||
val loadCoverOnlyWifi = appCtx.getPrefBoolean(PreferKey.loadCoverOnlyWifi, false)
|
||||
val loadCoverOnlyWifi get() = appCtx.getPrefBoolean(PreferKey.loadCoverOnlyWifi, false)
|
||||
|
||||
val showAddToShelfAlert get() = appCtx.getPrefBoolean(PreferKey.showAddToShelfAlert, true)
|
||||
|
||||
val doublePageHorizontal: String?
|
||||
get() = appCtx.getPrefString(PreferKey.doublePageHorizontal)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -105,7 +105,7 @@ object AudioPlay {
|
||||
book.durChapterIndex = index
|
||||
book.durChapterPos = 0
|
||||
durChapter = null
|
||||
saveRead(book)
|
||||
saveRead()
|
||||
play(context)
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ object AudioPlay {
|
||||
book.durChapterIndex = book.durChapterIndex - 1
|
||||
book.durChapterPos = 0
|
||||
durChapter = null
|
||||
saveRead(book)
|
||||
saveRead()
|
||||
play(context)
|
||||
}
|
||||
}
|
||||
@@ -134,17 +134,11 @@ object AudioPlay {
|
||||
book.durChapterIndex = book.durChapterIndex + 1
|
||||
book.durChapterPos = 0
|
||||
durChapter = null
|
||||
saveRead(book)
|
||||
saveRead()
|
||||
play(context)
|
||||
}
|
||||
}
|
||||
|
||||
fun addTimer() {
|
||||
val intent = Intent(appCtx, AudioPlayService::class.java)
|
||||
intent.action = IntentAction.addTimer
|
||||
appCtx.startService(intent)
|
||||
}
|
||||
|
||||
fun setTimer(minute: Int) {
|
||||
val intent = Intent(appCtx, AudioPlayService::class.java)
|
||||
intent.action = IntentAction.setTimer
|
||||
@@ -152,16 +146,18 @@ object AudioPlay {
|
||||
appCtx.startService(intent)
|
||||
}
|
||||
|
||||
fun saveRead(book: Book) {
|
||||
book.lastCheckCount = 0
|
||||
book.durChapterTime = System.currentTimeMillis()
|
||||
Coroutine.async {
|
||||
appDb.bookChapterDao.getChapter(book.bookUrl, book.durChapterIndex)?.let {
|
||||
book.durChapterTitle = it.getDisplayTitle(
|
||||
ContentProcessor.get(book.name, book.origin).getTitleReplaceRules()
|
||||
)
|
||||
fun saveRead() {
|
||||
book?.let { book ->
|
||||
book.lastCheckCount = 0
|
||||
book.durChapterTime = System.currentTimeMillis()
|
||||
Coroutine.async {
|
||||
appDb.bookChapterDao.getChapter(book.bookUrl, book.durChapterIndex)?.let {
|
||||
book.durChapterTitle = it.getDisplayTitle(
|
||||
ContentProcessor.get(book.name, book.origin).getTitleReplaceRules()
|
||||
)
|
||||
}
|
||||
book.save()
|
||||
}
|
||||
book.save()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,14 @@ object ReadAloud {
|
||||
fun play(
|
||||
context: Context,
|
||||
play: Boolean = true,
|
||||
pageIndex: Int = ReadBook.durPageIndex
|
||||
pageIndex: Int = ReadBook.durPageIndex,
|
||||
startPos: Int = 0
|
||||
) {
|
||||
val intent = Intent(context, aloudClass)
|
||||
intent.action = IntentAction.play
|
||||
intent.putExtra("play", play)
|
||||
intent.putExtra("pageIndex", pageIndex)
|
||||
|
||||
intent.putExtra("startPos", startPos)
|
||||
context.startService(intent)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.net.URLDecoder
|
||||
import java.nio.charset.Charset
|
||||
|
||||
class EpubFile(var book: Book) {
|
||||
@@ -116,7 +117,9 @@ class EpubFile(var book: Book) {
|
||||
* <image width="1038" height="670" xlink:href="..."/>
|
||||
* ...titlepage.xhtml
|
||||
*/
|
||||
if (chapter.url.contains("titlepage.xhtml")) {
|
||||
if (chapter.url.contains("titlepage.xhtml") ||
|
||||
chapter.url.contains("cover.xhtml")
|
||||
) {
|
||||
return "<img src=\"cover.jpeg\" />"
|
||||
}
|
||||
/*获取当前章节文本*/
|
||||
@@ -189,7 +192,7 @@ class EpubFile(var book: Book) {
|
||||
|
||||
private fun getImage(href: String): InputStream? {
|
||||
if (href == "cover.jpeg") return epubBook?.coverImage?.inputStream
|
||||
val abHref = href.replace("../", "")
|
||||
val abHref = URLDecoder.decode(href.replace("../", ""), "UTF-8")
|
||||
return epubBook?.resources?.getByHref(abHref)?.inputStream
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.documentfile.provider.DocumentFile
|
||||
import com.script.SimpleBindings
|
||||
import io.legado.app.R
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.BaseSource
|
||||
import io.legado.app.data.entities.Book
|
||||
@@ -16,6 +17,7 @@ import io.legado.app.help.BookHelp
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||
import io.legado.app.utils.*
|
||||
import org.jsoup.nodes.Entities
|
||||
import splitties.init.appCtx
|
||||
import java.io.*
|
||||
import java.util.regex.Pattern
|
||||
@@ -77,11 +79,12 @@ object LocalBook {
|
||||
throw TocEmptyException(appCtx.getString(R.string.chapter_list_empty))
|
||||
}
|
||||
val lh = LinkedHashSet(chapters)
|
||||
lh.forEachIndexed { index, bookChapter -> bookChapter.index = index }
|
||||
return ArrayList(lh)
|
||||
}
|
||||
|
||||
fun getContent(book: Book, chapter: BookChapter): String? {
|
||||
return try {
|
||||
val content = try {
|
||||
when {
|
||||
book.isEpub() -> {
|
||||
EpubFile.getContent(book, chapter)
|
||||
@@ -95,8 +98,15 @@ object LocalBook {
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printOnDebug()
|
||||
e.localizedMessage
|
||||
}
|
||||
AppLog.put("获取本地书籍内容失败\n${e.localizedMessage}", e)
|
||||
"获取本地书籍内容失败\n${e.localizedMessage}"
|
||||
}?.replace("<img", "< img", true)
|
||||
content ?: return null
|
||||
return kotlin.runCatching {
|
||||
Entities.unescape(content)
|
||||
}.onFailure {
|
||||
AppLog.put("HTML实体解码失败\n${it.localizedMessage}", it)
|
||||
}.getOrElse { content }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -111,6 +111,7 @@ object BookContent {
|
||||
}
|
||||
}
|
||||
var contentStr = content.toString()
|
||||
//全文替换
|
||||
val replaceRegex = contentRule.replaceRegex
|
||||
if (!replaceRegex.isNullOrEmpty()) {
|
||||
contentStr = analyzeRule.getString(replaceRegex, contentStr)
|
||||
|
||||
@@ -238,12 +238,11 @@ object WebBook {
|
||||
context: CoroutineContext = Dispatchers.IO
|
||||
): Coroutine<String> {
|
||||
return Coroutine.async(scope, context) {
|
||||
getContentAwait(scope, bookSource, book, bookChapter, nextChapterUrl, needSave)
|
||||
getContentAwait(bookSource, book, bookChapter, nextChapterUrl, needSave)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getContentAwait(
|
||||
scope: CoroutineScope,
|
||||
bookSource: BookSource,
|
||||
book: Book,
|
||||
bookChapter: BookChapter,
|
||||
|
||||
@@ -118,24 +118,19 @@ abstract class BaseReadAloudService : BaseService(),
|
||||
}
|
||||
|
||||
private fun newReadAloud(play: Boolean, pageIndex: Int, startPos: Int) {
|
||||
this.pageIndex = pageIndex
|
||||
textChapter = ReadBook.curTextChapter
|
||||
textChapter?.let { textChapter ->
|
||||
nowSpeak = 0
|
||||
readAloudNumber = textChapter.getReadLength(pageIndex) + startPos
|
||||
contentList.clear()
|
||||
if (getPrefBoolean(PreferKey.readAloudByPage)) {
|
||||
for (index in pageIndex..textChapter.lastIndex) {
|
||||
textChapter.getPage(index)?.text?.split("\n")?.let {
|
||||
contentList.addAll(it)
|
||||
val readAloudByPage = getPrefBoolean(PreferKey.readAloudByPage)
|
||||
textChapter.getNeedReadAloud(pageIndex, readAloudByPage, startPos)
|
||||
.split("\n").forEach { text ->
|
||||
if (text.isNotEmpty()) {
|
||||
contentList.add(text)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
textChapter.getUnRead(pageIndex).split("\n").forEach {
|
||||
if (it.isNotEmpty()) {
|
||||
contentList.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (play) play()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ class CheckSourceService : BaseService() {
|
||||
source.bookSourceComment = source.bookSourceComment
|
||||
?.split("\n\n")
|
||||
?.filterNot {
|
||||
it.startsWith("Error: ")
|
||||
it.startsWith("// Error: ")
|
||||
}?.joinToString("\n")
|
||||
//校验搜索书籍
|
||||
if (CheckSource.checkSearch) {
|
||||
@@ -186,7 +186,7 @@ class CheckSourceService : BaseService() {
|
||||
!is NoStackTraceException -> source.addGroup("网站失效")
|
||||
}
|
||||
source.bookSourceComment =
|
||||
"Error: ${it.localizedMessage}" + if (source.bookSourceComment.isNullOrBlank())
|
||||
"// Error: ${it.localizedMessage}" + if (source.bookSourceComment.isNullOrBlank())
|
||||
"" else "\n\n${source.bookSourceComment}"
|
||||
Debug.updateFinalMessage(source.bookSourceUrl, "校验失败:${it.localizedMessage}")
|
||||
}.onSuccess(searchCoroutine) {
|
||||
@@ -219,7 +219,6 @@ class CheckSourceService : BaseService() {
|
||||
//校验正文
|
||||
if (CheckSource.checkContent) {
|
||||
WebBook.getContentAwait(
|
||||
this,
|
||||
bookSource = source,
|
||||
book = mBook,
|
||||
bookChapter = toc.first(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.legado.app.ui.about
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import android.content.Context
|
||||
import android.icu.text.SimpleDateFormat
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
|
||||
@@ -46,7 +46,7 @@ class OnLineImportActivity :
|
||||
finallyDialog(getString(R.string.error), it)
|
||||
}
|
||||
intent.data?.let {
|
||||
val url = it.getQueryParameter("src")
|
||||
val url = it.query?.substringAfter("src=")
|
||||
if (url.isNullOrBlank()) {
|
||||
finish()
|
||||
return
|
||||
|
||||
@@ -2,12 +2,12 @@ package io.legado.app.ui.association
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BaseDialogFragment
|
||||
import io.legado.app.databinding.DialogVerificationCodeViewBinding
|
||||
@@ -17,7 +17,9 @@ import io.legado.app.help.glide.ImageLoader
|
||||
import io.legado.app.help.glide.OkHttpModelLoader
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.ui.widget.dialog.PhotoDialog
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.applyTint
|
||||
import io.legado.app.utils.setLayout
|
||||
import io.legado.app.utils.showDialogFragment
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
/**
|
||||
@@ -26,12 +28,18 @@ import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
* val key = "${sourceOrigin ?: ""}_verificationResult"
|
||||
* CacheManager.get(key)
|
||||
*/
|
||||
class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification_code_view), Toolbar.OnMenuItemClickListener {
|
||||
class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification_code_view),
|
||||
Toolbar.OnMenuItemClickListener {
|
||||
|
||||
constructor(imageUrl: String, sourceOrigin: String? = null) : this() {
|
||||
constructor(
|
||||
imageUrl: String,
|
||||
sourceOrigin: String? = null,
|
||||
sourceName: String? = null
|
||||
) : this() {
|
||||
arguments = Bundle().apply {
|
||||
putString("sourceOrigin", sourceOrigin)
|
||||
putString("imageUrl", imageUrl)
|
||||
putString("sourceOrigin", sourceOrigin)
|
||||
putString("sourceName", sourceName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,23 +55,23 @@ class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification
|
||||
initMenu()
|
||||
binding.run {
|
||||
toolBar.setBackgroundColor(primaryColor)
|
||||
val sourceOrigin = arguments?.getString("sourceOrigin")
|
||||
arguments?.getString("imageUrl")?.let { imageUrl ->
|
||||
ImageLoader.load(requireContext(), imageUrl).apply {
|
||||
sourceOrigin?.let {
|
||||
apply(
|
||||
RequestOptions().set(
|
||||
OkHttpModelLoader.sourceOriginOption,
|
||||
it
|
||||
arguments?.let { arguments ->
|
||||
toolBar.subtitle = arguments.getString("sourceName")
|
||||
val sourceOrigin = arguments.getString("sourceOrigin")
|
||||
arguments.getString("imageUrl")?.let { imageUrl ->
|
||||
ImageLoader.load(requireContext(), imageUrl).apply {
|
||||
sourceOrigin?.let {
|
||||
apply(
|
||||
RequestOptions().set(OkHttpModelLoader.sourceOriginOption, it)
|
||||
)
|
||||
)
|
||||
}
|
||||
}.error(R.drawable.image_loading_error)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(true)
|
||||
.into(verificationCodeImageView)
|
||||
verificationCodeImageView.setOnClickListener {
|
||||
showDialogFragment(PhotoDialog(imageUrl, sourceOrigin))
|
||||
}
|
||||
}.error(R.drawable.image_loading_error)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(true)
|
||||
.into(verificationCodeImageView)
|
||||
verificationCodeImageView.setOnClickListener {
|
||||
showDialogFragment(PhotoDialog(imageUrl, sourceOrigin))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +94,7 @@ class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification
|
||||
CacheManager.putMemory(key, it)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
|
||||
loadChapterList(book)
|
||||
}
|
||||
}
|
||||
saveRead(book)
|
||||
}
|
||||
}
|
||||
saveRead()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,19 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.adapter.DiffRecyclerAdapter
|
||||
import io.legado.app.base.adapter.ItemViewHolder
|
||||
import io.legado.app.data.entities.SearchBook
|
||||
import io.legado.app.databinding.ItemChangeSourceBinding
|
||||
import io.legado.app.utils.getCompatColor
|
||||
import io.legado.app.utils.gone
|
||||
import io.legado.app.utils.invisible
|
||||
import io.legado.app.utils.visible
|
||||
import splitties.init.appCtx
|
||||
import splitties.views.onLongClick
|
||||
|
||||
|
||||
@@ -68,10 +73,57 @@ class ChangeBookSourceAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
val score = callBack.getBookScore(item)
|
||||
if (score > 0) {
|
||||
binding.ivBad.gone()
|
||||
binding.ivGood.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_A200))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100))
|
||||
} else if (score < 0) {
|
||||
binding.ivGood.gone()
|
||||
binding.ivBad.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_A200))
|
||||
} else {
|
||||
binding.ivGood.visible()
|
||||
binding.ivBad.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerListener(holder: ItemViewHolder, binding: ItemChangeSourceBinding) {
|
||||
binding.ivGood.setOnClickListener {
|
||||
if (binding.ivBad.isVisible) {
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_A200))
|
||||
binding.ivBad.gone()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, 1)
|
||||
}
|
||||
} else {
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
binding.ivBad.visible()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.ivBad.setOnClickListener {
|
||||
if (binding.ivGood.isVisible) {
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_A200))
|
||||
binding.ivGood.gone()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, -1)
|
||||
}
|
||||
} else {
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100))
|
||||
binding.ivGood.visible()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
if (it.bookUrl != callBack.bookUrl) {
|
||||
@@ -120,5 +172,7 @@ class ChangeBookSourceAdapter(
|
||||
fun editSource(searchBook: SearchBook)
|
||||
fun disableSource(searchBook: SearchBook)
|
||||
fun deleteSource(searchBook: SearchBook)
|
||||
fun setBookScore(searchBook: SearchBook, score: Int)
|
||||
fun getBookScore(searchBook: SearchBook): Int
|
||||
}
|
||||
}
|
||||
@@ -294,6 +294,14 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_
|
||||
}
|
||||
}
|
||||
|
||||
override fun setBookScore(searchBook: SearchBook, score: Int) {
|
||||
viewModel.setBookScore(searchBook,score)
|
||||
}
|
||||
|
||||
override fun getBookScore(searchBook: SearchBook): Int {
|
||||
return viewModel.getBookScore(searchBook)
|
||||
}
|
||||
|
||||
private fun changeSource(searchBook: SearchBook, onSuccess: (() -> Unit)? = null) {
|
||||
waitDialog.setText(R.string.load_toc)
|
||||
waitDialog.show()
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.legado.app.data.entities.BookSource
|
||||
import io.legado.app.data.entities.SearchBook
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.SourceConfig
|
||||
import io.legado.app.help.coroutine.CompositeCoroutine
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.model.webBook.WebBook
|
||||
@@ -82,7 +83,23 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
searchCallback = null
|
||||
}
|
||||
}.map {
|
||||
searchBooks.sortedBy { it.originOrder }
|
||||
searchBooks.sortedWith { o1, o2 ->
|
||||
val o1bs = SourceConfig.getBookScore(o1.origin, o1.name, o1.author)
|
||||
val o2bs = SourceConfig.getBookScore(o2.origin, o2.name, o2.author)
|
||||
when {
|
||||
o1bs - o2bs > 0 -> -1
|
||||
o1bs - o2bs < 0 -> 1
|
||||
else -> {
|
||||
val o1ss = SourceConfig.getSourceScore(o1.origin)
|
||||
val o2ss = SourceConfig.getSourceScore(o2.origin)
|
||||
when {
|
||||
o1ss - o2ss > 0 -> -1
|
||||
o1ss - o2ss < 0 -> 1
|
||||
else -> o1.originOrder - o2.originOrder
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.flowOn(IO)
|
||||
|
||||
@Volatile
|
||||
@@ -351,6 +368,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
appDb.bookSourceDao.getBookSource(searchBook.origin)?.let { source ->
|
||||
appDb.bookSourceDao.delete(source)
|
||||
appDb.searchBookDao.delete(searchBook)
|
||||
SourceConfig.removeSource(source.bookSourceUrl)
|
||||
}
|
||||
}
|
||||
searchBooks.remove(searchBook)
|
||||
@@ -379,6 +397,17 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
||||
}
|
||||
}
|
||||
|
||||
fun setBookScore(searchBook: SearchBook, score: Int) {
|
||||
execute {
|
||||
SourceConfig.setBookScore(searchBook.origin, searchBook.name, searchBook.author, score)
|
||||
searchCallback?.upAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
fun getBookScore(searchBook: SearchBook): Int {
|
||||
return SourceConfig.getBookScore(searchBook.origin, searchBook.name, searchBook.author)
|
||||
}
|
||||
|
||||
interface SourceCallback {
|
||||
|
||||
fun searchSuccess(searchBook: SearchBook)
|
||||
|
||||
@@ -5,14 +5,19 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.adapter.DiffRecyclerAdapter
|
||||
import io.legado.app.base.adapter.ItemViewHolder
|
||||
import io.legado.app.data.entities.SearchBook
|
||||
import io.legado.app.databinding.ItemChangeSourceBinding
|
||||
import io.legado.app.utils.getCompatColor
|
||||
import io.legado.app.utils.gone
|
||||
import io.legado.app.utils.invisible
|
||||
import io.legado.app.utils.visible
|
||||
import splitties.init.appCtx
|
||||
import splitties.views.onLongClick
|
||||
|
||||
|
||||
@@ -68,10 +73,57 @@ class ChangeChapterSourceAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
val score = callBack.getBookScore(item)
|
||||
if (score > 0) {
|
||||
binding.ivBad.gone()
|
||||
binding.ivGood.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_A200))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100))
|
||||
} else if (score < 0) {
|
||||
binding.ivGood.gone()
|
||||
binding.ivBad.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_A200))
|
||||
} else {
|
||||
binding.ivGood.visible()
|
||||
binding.ivBad.visible()
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerListener(holder: ItemViewHolder, binding: ItemChangeSourceBinding) {
|
||||
binding.ivGood.setOnClickListener {
|
||||
if (binding.ivBad.isVisible) {
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_A200))
|
||||
binding.ivBad.gone()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, 1)
|
||||
}
|
||||
} else {
|
||||
DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100))
|
||||
binding.ivBad.visible()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.ivBad.setOnClickListener {
|
||||
if (binding.ivGood.isVisible) {
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_A200))
|
||||
binding.ivGood.gone()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, -1)
|
||||
}
|
||||
} else {
|
||||
DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100))
|
||||
binding.ivGood.visible()
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.setBookScore(it, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
getItem(holder.layoutPosition)?.let {
|
||||
callBack.openToc(it)
|
||||
@@ -118,5 +170,7 @@ class ChangeChapterSourceAdapter(
|
||||
fun editSource(searchBook: SearchBook)
|
||||
fun disableSource(searchBook: SearchBook)
|
||||
fun deleteSource(searchBook: SearchBook)
|
||||
fun setBookScore(searchBook: SearchBook, score: Int)
|
||||
fun getBookScore(searchBook: SearchBook): Int
|
||||
}
|
||||
}
|
||||
@@ -314,6 +314,14 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c
|
||||
}
|
||||
}
|
||||
|
||||
override fun setBookScore(searchBook: SearchBook, score: Int) {
|
||||
viewModel.setBookScore(searchBook, score)
|
||||
}
|
||||
|
||||
override fun getBookScore(searchBook: SearchBook): Int {
|
||||
return viewModel.getBookScore(searchBook)
|
||||
}
|
||||
|
||||
override fun clickChapter(bookChapter: BookChapter, nextChapterUrl: String?) {
|
||||
searchBook?.let {
|
||||
binding.loadingToc.show()
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ class ChangeChapterSourceViewModel(application: Application) :
|
||||
execute {
|
||||
val bookSource = appDb.bookSourceDao.getBookSource(book.origin)
|
||||
?: throw NoStackTraceException("书源不存在")
|
||||
WebBook.getContentAwait(this, bookSource, book, chapter, nextChapterUrl, false)
|
||||
WebBook.getContentAwait(bookSource, book, chapter, nextChapterUrl, false)
|
||||
}.onSuccess {
|
||||
success.invoke(it)
|
||||
}.onError {
|
||||
|
||||
@@ -21,6 +21,7 @@ import io.legado.app.data.entities.BookChapter
|
||||
import io.legado.app.data.entities.BookSource
|
||||
import io.legado.app.databinding.ActivityBookInfoBinding
|
||||
import io.legado.app.databinding.DialogEditTextBinding
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.lib.theme.bottomBackground
|
||||
@@ -247,8 +248,10 @@ class BookInfoActivity :
|
||||
|
||||
private fun showCover(book: Book) {
|
||||
binding.ivCover.load(book.getDisplayCover(), book.name, book.author, false, book.origin)
|
||||
BookCover.loadBlur(this, book.getDisplayCover())
|
||||
.into(binding.bgBook)
|
||||
if(!AppConfig.isEInkMode) {
|
||||
BookCover.loadBlur(this, book.getDisplayCover())
|
||||
.into(binding.bgBook)
|
||||
}
|
||||
}
|
||||
|
||||
private fun upLoading(isLoading: Boolean, chapterList: List<BookChapter>? = null) {
|
||||
|
||||
@@ -14,6 +14,8 @@ import io.legado.app.databinding.ItemArrangeBookBinding
|
||||
import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
||||
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
||||
import java.util.*
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
class BookAdapter(context: Context, val callBack: CallBack) :
|
||||
RecyclerAdapter<Book, ItemArrangeBookBinding>(context),
|
||||
@@ -121,6 +123,25 @@ class BookAdapter(context: Context, val callBack: CallBack) :
|
||||
callBack.upSelectCount()
|
||||
}
|
||||
|
||||
fun checkSelectedInterval() {
|
||||
val selectedPosition = linkedSetOf<Int>()
|
||||
getItems().forEachIndexed { index, it ->
|
||||
if (selectedBooks.contains(it)) {
|
||||
selectedPosition.add(index)
|
||||
}
|
||||
}
|
||||
val minPosition = Collections.min(selectedPosition)
|
||||
val maxPosition = Collections.max(selectedPosition)
|
||||
val itemCount = maxPosition - minPosition + 1
|
||||
for (i in minPosition..maxPosition) {
|
||||
getItem(i)?.let {
|
||||
selectedBooks.add(it)
|
||||
}
|
||||
}
|
||||
notifyItemRangeChanged(minPosition, itemCount, bundleOf(Pair("selected", null)))
|
||||
callBack.upSelectCount()
|
||||
}
|
||||
|
||||
private fun getGroupList(groupId: Long): List<String> {
|
||||
val groupNames = arrayListOf<String>()
|
||||
callBack.groupList.forEach {
|
||||
|
||||
@@ -192,6 +192,7 @@ class BookshelfManageActivity :
|
||||
viewModel.upCanUpdate(adapter.selection, false)
|
||||
R.id.menu_add_to_group -> selectGroup(addToGroupRequestCode, 0)
|
||||
R.id.menu_change_source -> showDialogFragment<SourcePickerDialog>()
|
||||
R.id.menu_check_selected_interval -> adapter.checkSelectedInterval()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ class ContentEditDialog : BaseDialogFragment(R.layout.dialog_content_edit) {
|
||||
content = null
|
||||
BookHelp.delContent(book, chapter)
|
||||
if (!book.isLocalBook()) ReadBook.bookSource?.let { bookSource ->
|
||||
WebBook.getContentAwait(this, bookSource, book, chapter)
|
||||
WebBook.getContentAwait(bookSource, book, chapter)
|
||||
}
|
||||
}
|
||||
return@execute content ?: let {
|
||||
|
||||
@@ -25,6 +25,7 @@ import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.help.AppWebDav
|
||||
import io.legado.app.help.BookHelp
|
||||
import io.legado.app.help.IntentData
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.ReadBookConfig
|
||||
import io.legado.app.help.config.ReadTipConfig
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
@@ -35,6 +36,7 @@ import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.model.ReadAloud
|
||||
import io.legado.app.model.ReadBook
|
||||
import io.legado.app.model.analyzeRule.AnalyzeRule
|
||||
import io.legado.app.receiver.TimeBatteryReceiver
|
||||
import io.legado.app.service.BaseReadAloudService
|
||||
import io.legado.app.ui.about.AppLogDialog
|
||||
@@ -182,6 +184,7 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||
super.onWindowFocusChanged(hasFocus)
|
||||
upSystemUiVisibility()
|
||||
binding.readMenu.upBrightnessState()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
@@ -960,31 +963,41 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
}
|
||||
|
||||
override fun payAction() {
|
||||
Coroutine.async(this) {
|
||||
val book = ReadBook.book ?: throw NoStackTraceException("no book")
|
||||
ReadBook.book?.let { book ->
|
||||
if (book.isLocalBook()) return
|
||||
val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
|
||||
?: throw NoStackTraceException("no chapter")
|
||||
val source = ReadBook.bookSource ?: throw NoStackTraceException("no book source")
|
||||
val payAction = source.getContentRule().payAction
|
||||
if (payAction.isNullOrEmpty()) {
|
||||
throw NoStackTraceException("no pay action")
|
||||
if (chapter == null) {
|
||||
toastOnUi("no chapter")
|
||||
return
|
||||
}
|
||||
JsUtils.evalJs(payAction) {
|
||||
it["java"] = source
|
||||
it["source"] = source
|
||||
it["book"] = book
|
||||
it["chapter"] = chapter
|
||||
}
|
||||
}.onSuccess {
|
||||
if (it.isNotBlank()) {
|
||||
startActivity<WebViewActivity> {
|
||||
putExtra("title", getString(R.string.chapter_pay))
|
||||
putExtra("url", it)
|
||||
IntentData.put(it, ReadBook.bookSource?.getHeaderMap(true))
|
||||
alert(R.string.chapter_pay) {
|
||||
setMessage(chapter.title)
|
||||
yesButton {
|
||||
Coroutine.async {
|
||||
val source = ReadBook.bookSource ?: throw NoStackTraceException("no book source")
|
||||
val payAction = source.getContentRule().payAction
|
||||
if (payAction.isNullOrEmpty()) {
|
||||
throw NoStackTraceException("no pay action")
|
||||
}
|
||||
val analyzeRule = AnalyzeRule(book, source)
|
||||
analyzeRule.setBaseUrl(chapter.url)
|
||||
analyzeRule.chapter = chapter
|
||||
analyzeRule.evalJS(payAction).toString()
|
||||
}.onSuccess {
|
||||
if (it.isNotBlank()) {
|
||||
startActivity<WebViewActivity> {
|
||||
putExtra("title", R.string.chapter_pay)
|
||||
putExtra("url", it)
|
||||
IntentData.put(it, ReadBook.bookSource?.getHeaderMap(true))
|
||||
}
|
||||
}
|
||||
}.onError {
|
||||
AppLog.putDebug(it.localizedMessage)
|
||||
toastOnUi(it.localizedMessage)
|
||||
}
|
||||
}
|
||||
noButton()
|
||||
}
|
||||
}.onError {
|
||||
toastOnUi(it.localizedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,13 +1160,17 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
override fun finish() {
|
||||
ReadBook.book?.let {
|
||||
if (!ReadBook.inBookshelf) {
|
||||
alert(title = getString(R.string.add_to_shelf)) {
|
||||
setMessage(getString(R.string.check_add_bookshelf, it.name))
|
||||
okButton {
|
||||
ReadBook.inBookshelf = true
|
||||
setResult(Activity.RESULT_OK)
|
||||
if (!AppConfig.showAddToShelfAlert) {
|
||||
viewModel.removeFromBookshelf { super.finish() }
|
||||
} else {
|
||||
alert(title = getString(R.string.add_to_shelf)) {
|
||||
setMessage(getString(R.string.check_add_bookshelf, it.name))
|
||||
okButton {
|
||||
ReadBook.inBookshelf = true
|
||||
setResult(Activity.RESULT_OK)
|
||||
}
|
||||
noButton { viewModel.removeFromBookshelf { super.finish() } }
|
||||
}
|
||||
noButton { viewModel.removeFromBookshelf { super.finish() } }
|
||||
}
|
||||
} else {
|
||||
super.finish()
|
||||
@@ -1190,6 +1207,7 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
}
|
||||
observeEvent<Boolean>(EventBus.UP_CONFIG) {
|
||||
upSystemUiVisibility()
|
||||
readView.upPageSlopSquare()
|
||||
readView.upBg()
|
||||
readView.upStyle()
|
||||
readView.upBgAlpha()
|
||||
|
||||
@@ -216,7 +216,6 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
||||
toc.first()
|
||||
}
|
||||
WebBook.getContentAwait(
|
||||
this,
|
||||
bookSource = source,
|
||||
book = book,
|
||||
bookChapter = toc[book.durChapterIndex],
|
||||
|
||||
@@ -43,10 +43,18 @@ class ReadMenu @JvmOverloads constructor(
|
||||
var cnaShowMenu: Boolean = false
|
||||
private val callBack: CallBack get() = activity as CallBack
|
||||
private val binding = ViewReadMenuBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
private lateinit var menuTopIn: Animation
|
||||
private lateinit var menuTopOut: Animation
|
||||
private lateinit var menuBottomIn: Animation
|
||||
private lateinit var menuBottomOut: Animation
|
||||
private val menuTopIn: Animation by lazy {
|
||||
loadAnimation(context, R.anim.anim_readbook_top_in)
|
||||
}
|
||||
private val menuTopOut: Animation by lazy {
|
||||
loadAnimation(context, R.anim.anim_readbook_top_out)
|
||||
}
|
||||
private val menuBottomIn: Animation by lazy {
|
||||
loadAnimation(context, R.anim.anim_readbook_bottom_in)
|
||||
}
|
||||
private val menuBottomOut: Animation by lazy {
|
||||
loadAnimation(context, R.anim.anim_readbook_bottom_out)
|
||||
}
|
||||
private val bgColor: Int = context.bottomBackground
|
||||
private val textColor: Int = context.getPrimaryTextColor(ColorUtils.isColorLight(bgColor))
|
||||
private val bottomBackgroundList: ColorStateList = Selector.colorBuild()
|
||||
@@ -71,6 +79,58 @@ class ReadMenu @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
private val menuInListener = object : Animation.AnimationListener {
|
||||
override fun onAnimationStart(animation: Animation) {
|
||||
binding.tvSourceAction.isGone = ReadBook.isLocalBook
|
||||
binding.tvLogin.isGone = ReadBook.bookSource?.loginUrl.isNullOrEmpty()
|
||||
binding.tvPay.isGone = ReadBook.bookSource?.loginUrl.isNullOrEmpty()
|
||||
|| ReadBook.curTextChapter?.isVip != true
|
||||
|| ReadBook.curTextChapter?.isPay == true
|
||||
callBack.upSystemUiVisibility()
|
||||
binding.llBrightness.visible(showBrightnessView)
|
||||
}
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
override fun onAnimationEnd(animation: Animation) {
|
||||
val navigationBarHeight =
|
||||
if (ReadBookConfig.hideNavigationBar) {
|
||||
activity?.navigationBarHeight ?: 0
|
||||
} else {
|
||||
0
|
||||
}
|
||||
binding.run {
|
||||
vwMenuBg.setOnClickListener { runMenuOut() }
|
||||
root.padding = 0
|
||||
when (activity?.navigationBarGravity) {
|
||||
Gravity.BOTTOM -> root.bottomPadding = navigationBarHeight
|
||||
Gravity.LEFT -> root.leftPadding = navigationBarHeight
|
||||
Gravity.RIGHT -> root.rightPadding = navigationBarHeight
|
||||
}
|
||||
}
|
||||
callBack.upSystemUiVisibility()
|
||||
if (!LocalConfig.readMenuHelpVersionIsLast) {
|
||||
callBack.showReadMenuHelp()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAnimationRepeat(animation: Animation) = Unit
|
||||
}
|
||||
private val menuOutListener = object : Animation.AnimationListener {
|
||||
override fun onAnimationStart(animation: Animation) {
|
||||
binding.vwMenuBg.setOnClickListener(null)
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animation) {
|
||||
this@ReadMenu.invisible()
|
||||
binding.titleBar.invisible()
|
||||
binding.bottomMenu.invisible()
|
||||
cnaShowMenu = false
|
||||
onMenuOutEnd?.invoke()
|
||||
callBack.upSystemUiVisibility()
|
||||
}
|
||||
|
||||
override fun onAnimationRepeat(animation: Animation) = Unit
|
||||
}
|
||||
|
||||
init {
|
||||
initView()
|
||||
@@ -141,19 +201,29 @@ class ReadMenu @JvmOverloads constructor(
|
||||
activity?.window?.attributes = params
|
||||
}
|
||||
|
||||
fun runMenuIn() {
|
||||
fun runMenuIn(anim: Boolean = !AppConfig.isEInkMode) {
|
||||
this.visible()
|
||||
binding.titleBar.visible()
|
||||
binding.bottomMenu.visible()
|
||||
binding.titleBar.startAnimation(menuTopIn)
|
||||
binding.bottomMenu.startAnimation(menuBottomIn)
|
||||
if (anim) {
|
||||
binding.titleBar.startAnimation(menuTopIn)
|
||||
binding.bottomMenu.startAnimation(menuBottomIn)
|
||||
} else {
|
||||
menuInListener.onAnimationStart(menuBottomIn)
|
||||
menuInListener.onAnimationEnd(menuBottomIn)
|
||||
}
|
||||
}
|
||||
|
||||
fun runMenuOut(onMenuOutEnd: (() -> Unit)? = null) {
|
||||
fun runMenuOut(anim: Boolean = !AppConfig.isEInkMode, onMenuOutEnd: (() -> Unit)? = null) {
|
||||
this.onMenuOutEnd = onMenuOutEnd
|
||||
if (this.isVisible) {
|
||||
binding.titleBar.startAnimation(menuTopOut)
|
||||
binding.bottomMenu.startAnimation(menuBottomOut)
|
||||
if (anim) {
|
||||
binding.titleBar.startAnimation(menuTopOut)
|
||||
binding.bottomMenu.startAnimation(menuBottomOut)
|
||||
} else {
|
||||
menuOutListener.onAnimationStart(menuBottomOut)
|
||||
menuOutListener.onAnimationEnd(menuBottomOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +358,9 @@ class ReadMenu @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
llReadAloud.onLongClick {
|
||||
runMenuOut { callBack.showReadAloudDialog() }
|
||||
runMenuOut {
|
||||
callBack.showReadAloudDialog()
|
||||
}
|
||||
}
|
||||
//界面
|
||||
llFont.setOnClickListener {
|
||||
@@ -306,66 +378,8 @@ class ReadMenu @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private fun initAnimation() {
|
||||
//显示菜单
|
||||
menuTopIn = AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_top_in)
|
||||
menuBottomIn = AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_bottom_in)
|
||||
menuTopIn.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationStart(animation: Animation) {
|
||||
binding.tvSourceAction.isGone = ReadBook.isLocalBook
|
||||
binding.tvLogin.isGone = ReadBook.bookSource?.loginUrl.isNullOrEmpty()
|
||||
binding.tvPay.isGone = ReadBook.bookSource?.loginUrl.isNullOrEmpty()
|
||||
|| ReadBook.curTextChapter?.isVip != true
|
||||
|| ReadBook.curTextChapter?.isPay == true
|
||||
callBack.upSystemUiVisibility()
|
||||
binding.llBrightness.visible(showBrightnessView)
|
||||
}
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
override fun onAnimationEnd(animation: Animation) {
|
||||
val navigationBarHeight =
|
||||
if (ReadBookConfig.hideNavigationBar) {
|
||||
activity?.navigationBarHeight ?: 0
|
||||
} else {
|
||||
0
|
||||
}
|
||||
binding.run {
|
||||
vwMenuBg.setOnClickListener { runMenuOut() }
|
||||
root.padding = 0
|
||||
when (activity?.navigationBarGravity) {
|
||||
Gravity.BOTTOM -> root.bottomPadding = navigationBarHeight
|
||||
Gravity.LEFT -> root.leftPadding = navigationBarHeight
|
||||
Gravity.RIGHT -> root.rightPadding = navigationBarHeight
|
||||
}
|
||||
}
|
||||
callBack.upSystemUiVisibility()
|
||||
if (!LocalConfig.readMenuHelpVersionIsLast) {
|
||||
callBack.showReadMenuHelp()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAnimationRepeat(animation: Animation) = Unit
|
||||
})
|
||||
|
||||
//隐藏菜单
|
||||
menuTopOut = AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_top_out)
|
||||
menuBottomOut =
|
||||
AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_bottom_out)
|
||||
menuTopOut.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationStart(animation: Animation) {
|
||||
binding.vwMenuBg.setOnClickListener(null)
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animation) {
|
||||
this@ReadMenu.invisible()
|
||||
binding.titleBar.invisible()
|
||||
binding.bottomMenu.invisible()
|
||||
cnaShowMenu = false
|
||||
onMenuOutEnd?.invoke()
|
||||
callBack.upSystemUiVisibility()
|
||||
}
|
||||
|
||||
override fun onAnimationRepeat(animation: Animation) = Unit
|
||||
})
|
||||
menuTopIn.setAnimationListener(menuInListener)
|
||||
menuTopOut.setAnimationListener(menuOutListener)
|
||||
}
|
||||
|
||||
fun upBookView() {
|
||||
|
||||
@@ -33,10 +33,8 @@ class SearchMenu @JvmOverloads constructor(
|
||||
private val callBack: CallBack get() = activity as CallBack
|
||||
private val binding = ViewSearchMenuBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
|
||||
private val menuBottomIn: Animation =
|
||||
AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_bottom_in)
|
||||
private val menuBottomOut: Animation =
|
||||
AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_bottom_out)
|
||||
private val menuBottomIn: Animation = loadAnimation(context, R.anim.anim_readbook_bottom_in)
|
||||
private val menuBottomOut: Animation = loadAnimation(context, R.anim.anim_readbook_bottom_out)
|
||||
private val bgColor: Int = context.bottomBackground
|
||||
private val textColor: Int = context.getPrimaryTextColor(ColorUtils.isColorLight(bgColor))
|
||||
private val bottomBackgroundList: ColorStateList =
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.preference.Preference
|
||||
import io.legado.app.R
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.ReadBookConfig
|
||||
import io.legado.app.lib.prefs.fragment.PreferenceFragment
|
||||
import io.legado.app.lib.theme.bottomBackground
|
||||
@@ -18,6 +19,7 @@ import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.ReadBook
|
||||
import io.legado.app.ui.book.read.ReadBookActivity
|
||||
import io.legado.app.ui.book.read.page.provider.ChapterProvider
|
||||
import io.legado.app.ui.widget.number.NumberPickerDialog
|
||||
import io.legado.app.utils.dpToPx
|
||||
import io.legado.app.utils.getPrefBoolean
|
||||
import io.legado.app.utils.postEvent
|
||||
@@ -70,9 +72,12 @@ class MoreConfigDialog : DialogFragment() {
|
||||
class ReadPreferenceFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val slopSquare by lazy { ViewConfiguration.get(context).scaledTouchSlop }
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_config_read)
|
||||
upPreferenceSummary(PreferKey.pageTouchSlop, slopSquare.toString())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@@ -137,9 +142,29 @@ class MoreConfigDialog : DialogFragment() {
|
||||
"clickRegionalConfig" -> {
|
||||
(activity as? ReadBookActivity)?.showClickRegionalConfig()
|
||||
}
|
||||
PreferKey.pageTouchSlop -> {
|
||||
NumberPickerDialog(requireContext())
|
||||
.setTitle(getString(R.string.page_touch_slop_dialog_title))
|
||||
.setMaxValue(9999)
|
||||
.setMinValue(0)
|
||||
.setValue(AppConfig.pageTouchSlop)
|
||||
.show {
|
||||
AppConfig.pageTouchSlop = it
|
||||
postEvent(EventBus.UP_CONFIG, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
private fun upPreferenceSummary(preferenceKey: String, value: String?) {
|
||||
val preference = findPreference<Preference>(preferenceKey) ?: return
|
||||
when (preferenceKey) {
|
||||
PreferKey.pageTouchSlop -> preference.summary =
|
||||
getString(R.string.page_touch_slop_summary, value)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -169,12 +169,14 @@ class TocRegexDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
||||
alertBinding.apply {
|
||||
tvRuleName.setText(tocRule.name)
|
||||
tvRuleRegex.setText(tocRule.rule)
|
||||
tvRuleExample.setText(tocRule.example)
|
||||
}
|
||||
customView { alertBinding.root }
|
||||
okButton {
|
||||
alertBinding.apply {
|
||||
tocRule.name = tvRuleName.text.toString()
|
||||
tocRule.rule = tvRuleRegex.text.toString()
|
||||
tocRule.example = tvRuleExample.text.toString()
|
||||
viewModel.saveRule(tocRule)
|
||||
}
|
||||
}
|
||||
@@ -200,6 +202,7 @@ class TocRegexDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
||||
if (payloads.isEmpty()) {
|
||||
root.setBackgroundColor(context.backgroundColor)
|
||||
rbRegexName.text = item.name
|
||||
titleExample.text = item.example
|
||||
rbRegexName.isChecked = item.name == selectedName
|
||||
swtEnabled.isChecked = item.enable
|
||||
} else {
|
||||
|
||||
@@ -446,7 +446,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
|
||||
return book.createBookMark().apply {
|
||||
chapterIndex = page.chapterIndex
|
||||
chapterPos = chapter.getReadLength(page.index) +
|
||||
page.getSelectStartLength(selectStart.lineIndex, selectStart.charIndex)
|
||||
page.getPosByLineColumn(selectStart.lineIndex, selectStart.charIndex)
|
||||
chapterName = chapter.title
|
||||
bookText = getSelectedText()
|
||||
}
|
||||
|
||||
@@ -82,13 +82,7 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
private val initialTextPos = TextPos(0, 0, 0)
|
||||
|
||||
val slopSquare by lazy { ViewConfiguration.get(context).scaledTouchSlop }
|
||||
val pageSlopSquare by lazy {
|
||||
if (AppConfig.pageTouchSlop == 0) {
|
||||
slopSquare
|
||||
} else {
|
||||
AppConfig.pageTouchSlop
|
||||
}
|
||||
}
|
||||
private var pageSlopSquare: Int = slopSquare
|
||||
private val tlRect = RectF()
|
||||
private val tcRect = RectF()
|
||||
private val trRect = RectF()
|
||||
@@ -112,6 +106,7 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
upBg()
|
||||
setWillNotDraw(false)
|
||||
upPageAnim()
|
||||
upPageSlopSquare()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,6 +248,9 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态栏
|
||||
*/
|
||||
fun upStatusBar() {
|
||||
curPage.upStatusBar()
|
||||
prevPage.upStatusBar()
|
||||
@@ -402,6 +400,9 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击
|
||||
*/
|
||||
private fun click(action: Int) {
|
||||
when (action) {
|
||||
0 -> callBack.showActionMenu()
|
||||
@@ -441,6 +442,9 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁事件
|
||||
*/
|
||||
fun onDestroy() {
|
||||
pageDelegate?.onDestroy()
|
||||
curPage.cancelSelect()
|
||||
@@ -511,6 +515,14 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
callBack.screenOffTimerStart()
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新滑动距离
|
||||
*/
|
||||
fun upPageSlopSquare() {
|
||||
val pageTouchSlop = AppConfig.pageTouchSlop
|
||||
this.pageSlopSquare = if (pageTouchSlop == 0) slopSquare else pageTouchSlop
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新样式
|
||||
*/
|
||||
@@ -563,10 +575,17 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
*/
|
||||
fun aloudStartSelect() {
|
||||
val selectStartPos = curPage.selectStartPos
|
||||
if (selectStartPos.relativePagePos > 0) {
|
||||
ReadBook.moveToNextPage()
|
||||
var pagePos = selectStartPos.relativePagePos
|
||||
val line = selectStartPos.lineIndex
|
||||
val column = selectStartPos.charIndex
|
||||
while (pagePos > 0) {
|
||||
if (!ReadBook.moveToNextPage()) {
|
||||
ReadBook.moveToNextChapter(false)
|
||||
}
|
||||
pagePos--
|
||||
}
|
||||
//TODO 未完成
|
||||
val startPos = curPage.textPage.getPosByLineColumn(line, column)
|
||||
ReadAloud.play(context, startPos = startPos)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.legado.app.ui.book.read.page.entities
|
||||
|
||||
import kotlin.math.min
|
||||
|
||||
@Suppress("unused")
|
||||
data class TextChapter(
|
||||
val position: Int,
|
||||
val title: String,
|
||||
@@ -61,6 +62,17 @@ data class TextChapter(
|
||||
return getReadLength(pageIndex + 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取内容
|
||||
*/
|
||||
fun getContent(): String {
|
||||
val stringBuilder = StringBuilder()
|
||||
pages.forEach {
|
||||
stringBuilder.append(it.text)
|
||||
}
|
||||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 获取未读文字
|
||||
*/
|
||||
@@ -75,14 +87,22 @@ data class TextChapter(
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取内容
|
||||
* @return 需要朗读的文本列表
|
||||
* @param pageIndex 起始页
|
||||
* @param pageSplit 是否分页
|
||||
* @param startPos 从当前页什么地方开始朗读
|
||||
*/
|
||||
fun getContent(): String {
|
||||
fun getNeedReadAloud(pageIndex: Int, pageSplit: Boolean, startPos: Int): String {
|
||||
val stringBuilder = StringBuilder()
|
||||
pages.forEach {
|
||||
stringBuilder.append(it.text)
|
||||
if (pages.isNotEmpty()) {
|
||||
for (index in pageIndex..pages.lastIndex) {
|
||||
stringBuilder.append(pages[index].text)
|
||||
if (pageSplit && !stringBuilder.endsWith("\n")) {
|
||||
stringBuilder.append("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString()
|
||||
return stringBuilder.substring(startPos).toString()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,9 @@ data class TextPage(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 底部对齐更新行位置
|
||||
*/
|
||||
fun upLinesPosition() {
|
||||
if (!ReadBookConfig.textBottomJustify) return
|
||||
if (textLines.size <= 1) return
|
||||
@@ -77,6 +80,9 @@ data class TextPage(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算文字位置
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
fun format(): TextPage {
|
||||
if (textLines.isEmpty()) isMsgPage = true
|
||||
@@ -105,9 +111,7 @@ data class TextPage(
|
||||
val cw = StaticLayout.getDesiredWidth(char, ChapterProvider.contentPaint)
|
||||
val x1 = x + cw
|
||||
textLine.textChars.add(
|
||||
TextChar(
|
||||
char, start = x, end = x1
|
||||
)
|
||||
TextChar(char, start = x, end = x1)
|
||||
)
|
||||
x = x1
|
||||
}
|
||||
@@ -118,6 +122,9 @@ data class TextPage(
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除朗读标志
|
||||
*/
|
||||
fun removePageAloudSpan(): TextPage {
|
||||
textLines.forEach { textLine ->
|
||||
textLine.isReadAloud = false
|
||||
@@ -125,6 +132,10 @@ data class TextPage(
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新朗读标志
|
||||
* @param aloudSpanStart 朗读文字开始位置
|
||||
*/
|
||||
fun upPageAloudSpan(aloudSpanStart: Int) {
|
||||
removePageAloudSpan()
|
||||
var lineStart = 0
|
||||
@@ -151,6 +162,9 @@ data class TextPage(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 阅读进度
|
||||
*/
|
||||
val readProgress: String
|
||||
get() {
|
||||
val df = DecimalFormat("0.0%")
|
||||
@@ -167,15 +181,24 @@ data class TextPage(
|
||||
return percent
|
||||
}
|
||||
|
||||
fun getSelectStartLength(lineIndex: Int, charIndex: Int): Int {
|
||||
/**
|
||||
* 根据行和列返回字符在本页的位置
|
||||
* @param lineIndex 字符在第几行
|
||||
* @param columnIndex 字符在第几列
|
||||
* @return 字符在本页位置
|
||||
*/
|
||||
fun getPosByLineColumn(lineIndex: Int, columnIndex: Int): Int {
|
||||
var length = 0
|
||||
val maxIndex = min(lineIndex, lineSize)
|
||||
for (index in 0 until maxIndex) {
|
||||
length += textLines[index].charSize
|
||||
}
|
||||
return length + charIndex
|
||||
return length + columnIndex
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 页面所在章节
|
||||
*/
|
||||
fun getTextChapter(): TextChapter? {
|
||||
ReadBook.curTextChapter?.let {
|
||||
if (it.position == chapterIndex) {
|
||||
|
||||
@@ -66,6 +66,7 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
||||
private var menu: Menu? = null
|
||||
private var precisionSearchMenuItem: MenuItem? = null
|
||||
private var groups = linkedSetOf<String>()
|
||||
private var isManualStopSearch = false
|
||||
private val searchFinishCallback: (isEmpty: Boolean) -> Unit = searchFinish@{ isEmpty ->
|
||||
val searchGroup = AppConfig.searchGroup
|
||||
if (!isEmpty || searchGroup.isEmpty()) return@searchFinish
|
||||
@@ -155,6 +156,7 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||
searchView.clearFocus()
|
||||
query?.let {
|
||||
isManualStopSearch = false
|
||||
viewModel.saveSearchKey(query)
|
||||
viewModel.searchKey = ""
|
||||
viewModel.search(it)
|
||||
@@ -221,6 +223,7 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
||||
.setPressedColor(ColorUtils.darkenColor(accentColor))
|
||||
.create()
|
||||
binding.fbStop.setOnClickListener {
|
||||
isManualStopSearch = true
|
||||
viewModel.stop()
|
||||
binding.refreshProgressBar.isAutoLoading = false
|
||||
}
|
||||
@@ -266,6 +269,9 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
||||
* 滚动到底部事件
|
||||
*/
|
||||
private fun scrollToBottom() {
|
||||
if (isManualStopSearch) {
|
||||
return
|
||||
}
|
||||
if (viewModel.isSearchLiveData.value == false
|
||||
&& viewModel.searchKey.isNotEmpty()
|
||||
&& loadMoreView.hasMore
|
||||
@@ -335,7 +341,7 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
|
||||
historyFlowJob?.cancel()
|
||||
historyFlowJob = launch {
|
||||
when {
|
||||
key.isNullOrBlank() -> appDb.searchKeywordDao.flowByUsage()
|
||||
key.isNullOrBlank() -> appDb.searchKeywordDao.flowByTime()
|
||||
else -> appDb.searchKeywordDao.flowSearch(key)
|
||||
}.conflate().collect {
|
||||
historyKeyAdapter.setItems(it)
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.BookSource
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.help.RuleComplete
|
||||
import io.legado.app.help.config.SourceConfig
|
||||
import io.legado.app.help.http.CookieStore
|
||||
import io.legado.app.help.http.newCallStrResponse
|
||||
import io.legado.app.help.http.okHttpClient
|
||||
@@ -40,6 +41,7 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat
|
||||
oldSourceUrl?.let {
|
||||
if (oldSourceUrl != source.bookSourceUrl) {
|
||||
appDb.bookSourceDao.delete(it)
|
||||
SourceConfig.removeSource(it)
|
||||
}
|
||||
}
|
||||
oldSourceUrl = source.bookSourceUrl
|
||||
|
||||
@@ -207,10 +207,12 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
|
||||
source.enabledExplore -> {
|
||||
iv.setColorFilter(Color.GREEN)
|
||||
iv.visible()
|
||||
iv.contentDescription = context.getString(R.string.tag_explore_enabled)
|
||||
}
|
||||
else -> {
|
||||
iv.setColorFilter(Color.RED)
|
||||
iv.visible()
|
||||
iv.contentDescription = context.getString(R.string.tag_explore_disabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.text.TextUtils
|
||||
import io.legado.app.base.BaseViewModel
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.BookSource
|
||||
import io.legado.app.help.config.SourceConfig
|
||||
import io.legado.app.utils.*
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
@@ -38,7 +39,12 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application)
|
||||
}
|
||||
|
||||
fun del(vararg sources: BookSource) {
|
||||
execute { appDb.bookSourceDao.delete(*sources) }
|
||||
execute {
|
||||
appDb.bookSourceDao.delete(*sources)
|
||||
sources.forEach {
|
||||
SourceConfig.removeSource(it.bookSourceUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun update(vararg bookSource: BookSource) {
|
||||
|
||||
@@ -22,10 +22,7 @@ import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||
import io.legado.app.utils.applyTint
|
||||
import io.legado.app.utils.requestInputMethod
|
||||
import io.legado.app.utils.setLayout
|
||||
import io.legado.app.utils.splitNotBlank
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -62,7 +59,11 @@ class GroupManageDialog : BaseDialogFragment(R.layout.dialog_recycler_view),
|
||||
it.map { group ->
|
||||
groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex))
|
||||
}
|
||||
adapter.setItems(groups.toList())
|
||||
adapter.setItems(
|
||||
groups.sortedWith { o1, o2 ->
|
||||
o1.cnCompare(o2)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ class WebViewActivity : VMBaseActivity<ActivityWebViewBinding, WebViewModel>() {
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
binding.titleBar.title = intent.getStringExtra("title") ?: getString(R.string.loading)
|
||||
binding.titleBar.subtitle = intent.getStringExtra("sourceName")
|
||||
viewModel.initData(intent) {
|
||||
val url = viewModel.baseUrl
|
||||
val headerMap = viewModel.headerMap
|
||||
@@ -124,12 +125,14 @@ class WebViewActivity : VMBaseActivity<ActivityWebViewBinding, WebViewModel>() {
|
||||
private fun upWebViewTheme() {
|
||||
if (AppConfig.isNightTheme) {
|
||||
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
|
||||
@Suppress("DEPRECATION")
|
||||
WebSettingsCompat.setForceDarkStrategy(
|
||||
binding.webView.settings,
|
||||
WebSettingsCompat.DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING
|
||||
)
|
||||
}
|
||||
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
|
||||
@Suppress("DEPRECATION")
|
||||
WebSettingsCompat.setForceDark(
|
||||
binding.webView.settings,
|
||||
WebSettingsCompat.FORCE_DARK_ON
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.legado.app.ui.config
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.InputType
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
@@ -116,6 +117,14 @@ class BackupConfigFragment : PreferenceFragment(),
|
||||
InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
|
||||
}
|
||||
}
|
||||
findPreference<EditTextPreference>(PreferKey.webDavDir)?.let {
|
||||
it.setOnBindEditTextListener { editText ->
|
||||
editText.text = AppConfig.webDavDir?.toEditable()
|
||||
}
|
||||
it.setOnPreferenceChangeListener { _, newValue ->
|
||||
(newValue as String).isNotBlank()
|
||||
}
|
||||
}
|
||||
upPreferenceSummary(PreferKey.webDavUrl, getPrefString(PreferKey.webDavUrl))
|
||||
upPreferenceSummary(PreferKey.webDavAccount, getPrefString(PreferKey.webDavAccount))
|
||||
upPreferenceSummary(PreferKey.webDavPassword, getPrefString(PreferKey.webDavPassword))
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import androidx.core.view.postDelayed
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.preference.ListPreference
|
||||
@@ -28,7 +27,9 @@ import io.legado.app.ui.widget.number.NumberPickerDialog
|
||||
import io.legado.app.utils.*
|
||||
import splitties.init.appCtx
|
||||
|
||||
|
||||
/**
|
||||
* 其它设置
|
||||
*/
|
||||
class OtherConfigFragment : PreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@@ -43,7 +44,6 @@ class OtherConfigFragment : PreferenceFragment(),
|
||||
AppConfig.defaultBookTreeUri = treeUri.toString()
|
||||
}
|
||||
}
|
||||
private val slopSquare by lazy { ViewConfiguration.get(context).scaledTouchSlop }
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
putPrefBoolean(PreferKey.processText, isProcessTextEnabled())
|
||||
@@ -60,7 +60,6 @@ class OtherConfigFragment : PreferenceFragment(),
|
||||
}
|
||||
upPreferenceSummary(PreferKey.checkSource, CheckSource.summary)
|
||||
upPreferenceSummary(PreferKey.bitmapCacheSize, AppConfig.bitmapCacheSize.toString())
|
||||
upPreferenceSummary(PreferKey.pageTouchSlop, slopSquare.toString())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@@ -120,16 +119,7 @@ class OtherConfigFragment : PreferenceFragment(),
|
||||
ImageProvider.bitmapLruCache.resize(ImageProvider.cacheSize)
|
||||
}
|
||||
}
|
||||
PreferKey.pageTouchSlop -> {
|
||||
NumberPickerDialog(requireContext())
|
||||
.setTitle(getString(R.string.page_touch_slop_dialog_title))
|
||||
.setMaxValue(9999)
|
||||
.setMinValue(0)
|
||||
.setValue(AppConfig.pageTouchSlop)
|
||||
.show {
|
||||
AppConfig.pageTouchSlop = it
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
@@ -181,7 +171,6 @@ class OtherConfigFragment : PreferenceFragment(),
|
||||
PreferKey.threadCount -> preference.summary = getString(R.string.threads_num, value)
|
||||
PreferKey.webPort -> preference.summary = getString(R.string.web_port_summary, value)
|
||||
PreferKey.bitmapCacheSize -> preference.summary = getString(R.string.bitmap_cache_size_summary, value)
|
||||
PreferKey.pageTouchSlop -> preference.summary = getString(R.string.page_touch_slop_summary, value)
|
||||
else -> if (preference is ListPreference) {
|
||||
val index = preference.findIndexOfValue(value)
|
||||
// Set the summary to reflect the new value.
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.legado.app.data.entities.BookSource
|
||||
import io.legado.app.data.entities.rule.ExploreKind
|
||||
import io.legado.app.databinding.ItemFilletTextBinding
|
||||
import io.legado.app.databinding.ItemFindBookBinding
|
||||
import io.legado.app.help.config.SourceConfig
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.lib.theme.accentColor
|
||||
import io.legado.app.ui.login.SourceLoginActivity
|
||||
@@ -174,6 +175,7 @@ class ExploreAdapter(context: Context, val callBack: CallBack) :
|
||||
}
|
||||
R.id.menu_del -> Coroutine.async(callBack.scope) {
|
||||
appDb.bookSourceDao.delete(source)
|
||||
SourceConfig.removeSource(source.bookSourceUrl)
|
||||
}
|
||||
}
|
||||
true
|
||||
|
||||
@@ -63,6 +63,7 @@ class RssAdapter(context: Context, val callBack: CallBack) :
|
||||
R.id.menu_top -> callBack.toTop(rssSource)
|
||||
R.id.menu_edit -> callBack.edit(rssSource)
|
||||
R.id.menu_del -> callBack.del(rssSource)
|
||||
R.id.menu_disable -> callBack.disable(rssSource)
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -74,5 +75,6 @@ class RssAdapter(context: Context, val callBack: CallBack) :
|
||||
fun toTop(rssSource: RssSource)
|
||||
fun edit(rssSource: RssSource)
|
||||
fun del(rssSource: RssSource)
|
||||
fun disable(rssSource: RssSource)
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ class RssFragment : VMBaseFragment<RssSourceViewModel>(R.layout.fragment_rss),
|
||||
private fun initGroupData() {
|
||||
groupsFlowJob?.cancel()
|
||||
groupsFlowJob = launch {
|
||||
appDb.rssSourceDao.flowGroup().conflate().collect {
|
||||
appDb.rssSourceDao.flowGroupEnabled().conflate().collect {
|
||||
groups.clear()
|
||||
it.map { group ->
|
||||
groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex))
|
||||
@@ -181,4 +181,8 @@ class RssFragment : VMBaseFragment<RssSourceViewModel>(R.layout.fragment_rss),
|
||||
override fun del(rssSource: RssSource) {
|
||||
viewModel.del(rssSource)
|
||||
}
|
||||
|
||||
override fun disable(rssSource: RssSource) {
|
||||
viewModel.disable(rssSource)
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
||||
SelectItem(getString(R.string.action_save), "save"),
|
||||
SelectItem(getString(R.string.select_folder), "selectFolder")
|
||||
)
|
||||
) { _, charSequence, i ->
|
||||
) { _, charSequence, _ ->
|
||||
when (charSequence.value) {
|
||||
"save" -> saveImage(webPic)
|
||||
"selectFolder" -> selectSaveFolder(null)
|
||||
@@ -219,12 +219,14 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
||||
private fun upWebViewTheme() {
|
||||
if (AppConfig.isNightTheme) {
|
||||
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
|
||||
@Suppress("DEPRECATION")
|
||||
WebSettingsCompat.setForceDarkStrategy(
|
||||
binding.webView.settings,
|
||||
WebSettingsCompat.DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING
|
||||
)
|
||||
}
|
||||
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
|
||||
@Suppress("DEPRECATION")
|
||||
WebSettingsCompat.setForceDark(
|
||||
binding.webView.settings,
|
||||
WebSettingsCompat.FORCE_DARK_ON
|
||||
|
||||
@@ -65,7 +65,11 @@ class GroupManageDialog : BaseDialogFragment(R.layout.dialog_recycler_view),
|
||||
it.map { group ->
|
||||
groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex))
|
||||
}
|
||||
adapter.setItems(groups.toList())
|
||||
adapter.setItems(
|
||||
groups.sortedWith { o1, o2 ->
|
||||
o1.cnCompare(o2)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceView
|
||||
override val viewModel by viewModels<RssSourceViewModel>()
|
||||
private val importRecordKey = "rssSourceRecordKey"
|
||||
private val adapter by lazy { RssSourceAdapter(this, this) }
|
||||
private val searchView: SearchView by lazy {
|
||||
binding.titleBar.findViewById(R.id.search_view)
|
||||
}
|
||||
private var sourceFlowJob: Job? = null
|
||||
private var groups = hashSetOf<String>()
|
||||
private var groupMenu: SubMenu? = null
|
||||
@@ -120,10 +123,21 @@ class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceView
|
||||
R.id.menu_import_qr -> qrCodeResult.launch()
|
||||
R.id.menu_group_manage -> showDialogFragment<GroupManageDialog>()
|
||||
R.id.menu_import_default -> viewModel.importDefault()
|
||||
R.id.menu_enabled_group -> {
|
||||
searchView.setQuery(getString(R.string.enabled), true)
|
||||
}
|
||||
R.id.menu_disabled_group -> {
|
||||
searchView.setQuery(getString(R.string.disabled), true)
|
||||
}
|
||||
R.id.menu_group_login -> {
|
||||
searchView.setQuery(getString(R.string.need_login), true)
|
||||
}
|
||||
R.id.menu_group_null -> {
|
||||
searchView.setQuery(getString(R.string.no_group), true)
|
||||
}
|
||||
R.id.menu_help -> showHelp()
|
||||
else -> if (item.groupId == R.id.source_group) {
|
||||
binding.titleBar.findViewById<SearchView>(R.id.search_view)
|
||||
.setQuery("group:${item.title}", true)
|
||||
searchView.setQuery("group:${item.title}", true)
|
||||
}
|
||||
}
|
||||
return super.onCompatOptionsItemSelected(item)
|
||||
@@ -144,6 +158,7 @@ class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceView
|
||||
R.id.menu_share_source -> viewModel.saveToFile(adapter.selection) {
|
||||
share(it)
|
||||
}
|
||||
R.id.menu_check_selected_interval -> adapter.checkSelectedInterval()
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -240,6 +255,18 @@ class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceView
|
||||
searchKey.isNullOrBlank() -> {
|
||||
appDb.rssSourceDao.flowAll()
|
||||
}
|
||||
searchKey == getString(R.string.enabled) -> {
|
||||
appDb.rssSourceDao.flowEnabled()
|
||||
}
|
||||
searchKey == getString(R.string.disabled) -> {
|
||||
appDb.rssSourceDao.flowDisabled()
|
||||
}
|
||||
searchKey == getString(R.string.need_login) -> {
|
||||
appDb.rssSourceDao.flowLogin()
|
||||
}
|
||||
searchKey == getString(R.string.no_group) -> {
|
||||
appDb.rssSourceDao.flowNoGroup()
|
||||
}
|
||||
searchKey.startsWith("group:") -> {
|
||||
val key = searchKey.substringAfter("group:")
|
||||
appDb.rssSourceDao.flowGroupSearch(key)
|
||||
|
||||
@@ -17,6 +17,7 @@ import io.legado.app.lib.theme.backgroundColor
|
||||
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
|
||||
import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
||||
import io.legado.app.utils.ColorUtils
|
||||
import java.util.*
|
||||
|
||||
|
||||
class RssSourceAdapter(context: Context, val callBack: CallBack) :
|
||||
@@ -151,6 +152,25 @@ class RssSourceAdapter(context: Context, val callBack: CallBack) :
|
||||
callBack.upCountView()
|
||||
}
|
||||
|
||||
fun checkSelectedInterval() {
|
||||
val selectedPosition = linkedSetOf<Int>()
|
||||
getItems().forEachIndexed { index, it ->
|
||||
if (selected.contains(it)) {
|
||||
selectedPosition.add(index)
|
||||
}
|
||||
}
|
||||
val minPosition = Collections.min(selectedPosition)
|
||||
val maxPosition = Collections.max(selectedPosition)
|
||||
val itemCount = maxPosition - minPosition + 1
|
||||
for (i in minPosition..maxPosition) {
|
||||
getItem(i)?.let {
|
||||
selected.add(it)
|
||||
}
|
||||
}
|
||||
notifyItemRangeChanged(minPosition, itemCount, bundleOf(Pair("selected", null)))
|
||||
callBack.upCountView()
|
||||
}
|
||||
|
||||
private fun showMenu(view: View, position: Int) {
|
||||
val source = getItem(position) ?: return
|
||||
val popupMenu = PopupMenu(context, view)
|
||||
|
||||
@@ -133,4 +133,11 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application)
|
||||
}
|
||||
}
|
||||
|
||||
fun disable(rssSource: RssSource) {
|
||||
execute {
|
||||
rssSource.enabled = false
|
||||
appDb.rssSourceDao.update(rssSource)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import io.legado.app.constant.AppPattern.dataUriRegex
|
||||
import android.icu.text.Collator
|
||||
import android.icu.util.ULocale
|
||||
import android.net.Uri
|
||||
import android.text.Editable
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@@ -13,6 +14,8 @@ fun String?.safeTrim() = if (this.isNullOrBlank()) null else this.trim()
|
||||
|
||||
fun String?.isContentScheme(): Boolean = this?.startsWith("content://") == true
|
||||
|
||||
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
|
||||
|
||||
fun String.parseToUri(): Uri {
|
||||
return if (isContentScheme()) {
|
||||
Uri.parse(this)
|
||||
|
||||
@@ -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>
|
||||
@@ -3,32 +3,28 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tool="http://schemas.android.com/tools"
|
||||
android:id="@+id/root_view"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background"
|
||||
android:padding="10dp">
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.5" />
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<io.legado.app.ui.book.read.config.TextFontWeightConverter
|
||||
android:id="@+id/text_font_weight_converter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textSize="14sp"
|
||||
app:isBottomBackground="true"
|
||||
app:radius="3dp" />
|
||||
@@ -42,12 +38,12 @@
|
||||
android:id="@+id/tv_text_font"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:text="@string/text_font"
|
||||
android:gravity="center"
|
||||
android:textSize="14sp"
|
||||
app:isBottomBackground="true"
|
||||
app:radius="3dp" />
|
||||
@@ -61,12 +57,12 @@
|
||||
android:id="@+id/tv_text_indent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:text="@string/text_indent"
|
||||
android:gravity="center"
|
||||
android:textSize="14sp"
|
||||
app:isBottomBackground="true"
|
||||
app:radius="3dp" />
|
||||
@@ -80,11 +76,11 @@
|
||||
android:id="@+id/chinese_converter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textSize="14sp"
|
||||
app:isBottomBackground="true"
|
||||
app:radius="3dp" />
|
||||
@@ -98,12 +94,12 @@
|
||||
android:id="@+id/tv_padding"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:text="@string/padding"
|
||||
android:gravity="center"
|
||||
android:textSize="14sp"
|
||||
app:isBottomBackground="true"
|
||||
app:radius="3dp" />
|
||||
@@ -117,30 +113,24 @@
|
||||
android:id="@+id/tv_tip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:text="@string/information"
|
||||
android:gravity="center"
|
||||
android:textSize="14sp"
|
||||
app:isBottomBackground="true"
|
||||
app:radius="3dp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.5" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<io.legado.app.ui.widget.DetailSeekBar
|
||||
android:id="@+id/dsb_text_size"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:isBottomBackground="true"
|
||||
app:max="45"
|
||||
app:title="@string/text_size" />
|
||||
@@ -149,8 +139,7 @@
|
||||
android:id="@+id/dsb_text_letter_spacing"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
app:isBottomBackground="true"
|
||||
app:max="100"
|
||||
app:title="@string/text_letter_spacing" />
|
||||
@@ -159,8 +148,7 @@
|
||||
android:id="@+id/dsb_line_size"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
app:isBottomBackground="true"
|
||||
app:max="20"
|
||||
app:title="@string/line_size" />
|
||||
@@ -169,8 +157,7 @@
|
||||
android:id="@+id/dsb_paragraph_spacing"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
app:isBottomBackground="true"
|
||||
app:max="20"
|
||||
app:title="@string/paragraph_size" />
|
||||
@@ -179,36 +166,37 @@
|
||||
android:id="@+id/vw_bg_fg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.8dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:background="@color/btn_bg_press" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_page_anim"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:text="@string/page_anim" />
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:alpha="0.75"
|
||||
android:text="@string/page_anim"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_page_anim"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center">
|
||||
android:layout_marginHorizontal="11dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<io.legado.app.lib.theme.view.ThemeRadioNoButton
|
||||
android:id="@+id/rb_anim0"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_margin="5dp"
|
||||
android:padding="5dp"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/page_anim_cover"
|
||||
app:isBottomBackground="true" />
|
||||
@@ -217,11 +205,11 @@
|
||||
android:id="@+id/rb_anim1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_margin="5dp"
|
||||
android:padding="5dp"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/page_anim_slide"
|
||||
app:isBottomBackground="true" />
|
||||
@@ -230,11 +218,11 @@
|
||||
android:id="@+id/rb_simulation_anim"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_margin="5dp"
|
||||
android:padding="5dp"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/page_anim_simulation"
|
||||
app:isBottomBackground="true" />
|
||||
@@ -243,11 +231,11 @@
|
||||
android:id="@+id/rb_scroll_anim"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_margin="5dp"
|
||||
android:padding="5dp"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/page_anim_scroll"
|
||||
app:isBottomBackground="true" />
|
||||
@@ -256,11 +244,11 @@
|
||||
android:id="@+id/rb_no_anim"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_margin="5dp"
|
||||
android:padding="5dp"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/page_anim_none"
|
||||
app:isBottomBackground="true" />
|
||||
@@ -271,24 +259,25 @@
|
||||
android:id="@+id/vw_bg_fg1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.8dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:background="@color/btn_bg_press" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_bg_ts"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:text="@string/text_bg_style" />
|
||||
android:alpha="0.75"
|
||||
android:text="@string/text_bg_style"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_share_layout"
|
||||
@@ -300,8 +289,8 @@
|
||||
android:id="@+id/cb_share_layout"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_marginLeft="6dp" />
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -309,7 +298,11 @@
|
||||
android:id="@+id/rv_style"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tool:listitem="@layout/item_read_style" />
|
||||
|
||||
|
||||
@@ -10,26 +10,26 @@
|
||||
android:id="@+id/tool_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background_menu"
|
||||
android:elevation="5dp"
|
||||
android:theme="?attr/actionBarStyle"
|
||||
android:background="@color/background_menu"
|
||||
app:title="@string/input_verification_code"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||
app:title="@string/input_verification_code"
|
||||
app:titleTextAppearance="@style/ToolbarTitle" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/verification_code_image_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:scaleType="centerCrop"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
<io.legado.app.ui.widget.text.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="3dp"
|
||||
android:layout_marginTop="8dp">
|
||||
android:layout_marginTop="8dp"
|
||||
android:padding="3dp">
|
||||
|
||||
<io.legado.app.lib.theme.view.ThemeEditText
|
||||
android:id="@+id/verification_code"
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_more_vert"
|
||||
android:tint="@color/primaryText"
|
||||
android:contentDescription="@string/more_menu"
|
||||
app:layout_constraintBottom_toTopOf="@id/iv_debug_text"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
@@ -63,7 +64,6 @@
|
||||
android:id="@+id/iv_explore"
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:contentDescription="@string/more_menu"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@color/md_green_600"
|
||||
app:layout_constraintRight_toRightOf="@id/iv_menu_more"
|
||||
|
||||
@@ -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>
|
||||
@@ -42,5 +42,6 @@
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_more_vert"
|
||||
android:tint="@color/primaryText"
|
||||
android:contentDescription="@string/more_menu"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
</LinearLayout>
|
||||
@@ -42,6 +42,7 @@
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/more_menu"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_more_vert"
|
||||
android:tint="@color/primaryText"
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_more_vert"
|
||||
android:tint="@color/primaryText"
|
||||
android:contentDescription="@string/more_menu"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/more_menu"
|
||||
android:tooltipText="@string/more_menu"
|
||||
android:contentDescription="@string/delete"
|
||||
android:tooltipText="@string/delete"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_clear_all"
|
||||
android:tint="@color/primaryText"
|
||||
|
||||
@@ -3,45 +3,56 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:padding="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="vertical">
|
||||
|
||||
<io.legado.app.lib.theme.view.ThemeRadioButton
|
||||
android:id="@+id/rb_regex_name"
|
||||
android:layout_width="0dp"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical">
|
||||
<io.legado.app.lib.theme.view.ThemeRadioButton
|
||||
android:id="@+id/rb_regex_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="1" />
|
||||
|
||||
<io.legado.app.lib.theme.view.ThemeSwitch
|
||||
android:id="@+id/swt_enabled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/iv_edit"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/edit"
|
||||
android:padding="6dp"
|
||||
android:tooltipText="@string/edit"
|
||||
android:src="@drawable/ic_edit"
|
||||
android:tint="@color/primaryText"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/iv_delete"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/delete"
|
||||
android:tooltipText="@string/delete"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_clear_all"
|
||||
android:tint="@color/primaryText"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_example"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="1" />
|
||||
|
||||
<io.legado.app.lib.theme.view.ThemeSwitch
|
||||
android:id="@+id/swt_enabled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/iv_edit"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/edit"
|
||||
android:padding="6dp"
|
||||
android:tooltipText="@string/edit"
|
||||
android:src="@drawable/ic_edit"
|
||||
android:tint="@color/primaryText"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/iv_delete"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/more_menu"
|
||||
android:tooltipText="@string/more_menu"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_clear_all"
|
||||
android:tint="@color/primaryText"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -50,6 +50,7 @@
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_more_vert"
|
||||
android:tint="@color/primaryText"
|
||||
android:contentDescription="@string/more_menu"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
Loaded 100 of 115 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user