@ -0,0 +1,32 @@ |
||||
#更新fork |
||||
name: update fork |
||||
|
||||
on: |
||||
schedule: |
||||
- cron: '0 16 * * *' #设置定时任务 |
||||
|
||||
jobs: |
||||
build: |
||||
runs-on: ubuntu-latest |
||||
if: ${{ github.event.repository.owner.id == github.event.sender.id && github.actor != 'gedoor' }} |
||||
steps: |
||||
- name: Checkout |
||||
uses: actions/checkout@v2 |
||||
with: |
||||
fetch-depth: 0 |
||||
- name: Install git |
||||
run: | |
||||
sudo apt-get update |
||||
sudo apt-get -y install git |
||||
- name: Set env |
||||
run: | |
||||
git config --global user.email "github-actions@github.com" |
||||
git config --global user.name "github-actions" |
||||
- name: Update fork |
||||
run: | |
||||
git remote add upstream https://github.com/gedoor/legado.git |
||||
git remote -v |
||||
git fetch upstream |
||||
git checkout master |
||||
git merge upstream/master |
||||
git push origin master |
@ -0,0 +1,57 @@ |
||||
name: Android CI |
||||
|
||||
on: |
||||
release: |
||||
types: [published] |
||||
push: |
||||
branches: |
||||
- master |
||||
# tags: |
||||
# - '3.*' |
||||
# pull_request: |
||||
# branches: |
||||
# - master |
||||
# watch: |
||||
# types: [started] |
||||
# schedule: |
||||
# - cron: '0 4 * * *' |
||||
|
||||
jobs: |
||||
build: |
||||
|
||||
runs-on: ubuntu-latest |
||||
|
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- name: set up JDK 1.8 |
||||
uses: actions/setup-java@v1 |
||||
with: |
||||
java-version: 1.8 |
||||
- name: clear 18PlusList.txt |
||||
run: | |
||||
echo "清空18PlusList.txt" |
||||
echo "">$GITHUB_WORKSPACE/app/src/main/assets/18PlusList.txt |
||||
- name: release apk sign |
||||
run: | |
||||
echo "给apk增加签名" |
||||
cp $GITHUB_WORKSPACE/.github/workflows/legado.jks $GITHUB_WORKSPACE/app/legado.jks |
||||
sed '$a\RELEASE_STORE_FILE=./legado.jks' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_ALIAS=legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_STORE_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
- name: apk live together |
||||
run: | |
||||
echo "设置apk共存" |
||||
sed "s/'.release'/'.releaseA'/" $GITHUB_WORKSPACE/app/build.gradle -i |
||||
sed 's/.release/.releaseA/' $GITHUB_WORKSPACE/app/google-services.json -i |
||||
- name: build with gradle |
||||
run: | |
||||
echo "开始进行release构建" |
||||
chmod +x gradlew |
||||
./gradlew assembleAppRelease |
||||
- name : upload apk |
||||
uses: actions/upload-artifact@master |
||||
if: always() |
||||
with: |
||||
name: legado apk |
||||
path: ${{ github.workspace }}/app/build/outputs/apk/app/release |
@ -0,0 +1,169 @@ |
||||
# 阅读API |
||||
## 对于Web的配置 |
||||
您需要先在设置中启用"Web 服务"。 |
||||
## 使用 |
||||
### Web |
||||
以下说明假设您的操作在本机进行,且开放端口为1234。 |
||||
如果您要从远程计算机访问[阅读](),请将`127.0.0.1`替换成手机IP。 |
||||
#### 插入单个书源 |
||||
``` |
||||
URL = http://127.0.0.1:1234/saveSource |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt) |
||||
|
||||
#### 插入多个书源 |
||||
``` |
||||
URL = http://127.0.0.1:1234/saveSources |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 获取书源 |
||||
``` |
||||
URL = http://127.0.0.1:1234/getSource?url=xxx |
||||
Method = GET |
||||
``` |
||||
|
||||
获取指定URL对应的书源信息。 |
||||
|
||||
#### 获取所有书源 |
||||
``` |
||||
URL = http://127.0.0.1:1234/getSources |
||||
Method = GET |
||||
``` |
||||
|
||||
获取APP内的所有书源。 |
||||
|
||||
#### 删除多个书源 |
||||
``` |
||||
URL = http://127.0.0.1:1234/deleteSources |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 插入书籍 |
||||
``` |
||||
URL = http://127.0.0.1:1234/saveBook |
||||
Method = POST |
||||
``` |
||||
|
||||
请求BODY内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/Book.kt)。 |
||||
|
||||
#### 获取所有书籍 |
||||
``` |
||||
URL = http://127.0.0.1:1234/getBookshelf |
||||
Method = GET |
||||
``` |
||||
|
||||
获取APP内的所有书籍。 |
||||
|
||||
#### 获取书籍章节列表 |
||||
``` |
||||
URL = http://127.0.0.1:1234/getChapterList?url=xxx |
||||
Method = GET |
||||
``` |
||||
|
||||
获取指定图书的章节列表。 |
||||
|
||||
#### 获取书籍内容 |
||||
|
||||
``` |
||||
URL = http://127.0.0.1:1234/getBookContent?url=xxx&index=1 |
||||
Method = GET |
||||
``` |
||||
|
||||
获取指定图书的第`index`章节的文本内容。 |
||||
|
||||
### Content Provider |
||||
* 需声明`io.legado.READ_WRITE`权限 |
||||
* `providerHost`为`包名.readerProvider`, 如`io.legado.app.release.readerProvider`,不同包的地址不同,防止冲突安装失败 |
||||
* 以下出现的`providerHost`请自行替换 |
||||
#### 插入单个书源 |
||||
``` |
||||
URL = content://providerHost/source/insert |
||||
Method = insert |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt) |
||||
|
||||
#### 插入多个书源 |
||||
``` |
||||
URL = content://providerHost/sources/insert |
||||
Method = insert |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 获取书源 |
||||
``` |
||||
URL = content://providerHost/source/query?url=xxx |
||||
Method = query |
||||
``` |
||||
|
||||
获取指定URL对应的书源信息。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 获取所有书源 |
||||
``` |
||||
URL = content://providerHost/sources/query |
||||
Method = query |
||||
``` |
||||
|
||||
获取APP内的所有书源。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 删除多个书源 |
||||
``` |
||||
URL = content://providerHost/sources/delete |
||||
Method = delete |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt),**为数组格式**。 |
||||
|
||||
#### 插入书籍 |
||||
``` |
||||
URL = content://providerHost/book/insert |
||||
Method = insert |
||||
``` |
||||
|
||||
创建`Key="json"`的`ContentValues`,内容为`JSON`字符串, |
||||
格式参考[这个文件](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/data/entities/Book.kt)。 |
||||
|
||||
#### 获取所有书籍 |
||||
``` |
||||
URL = content://providerHost/books/query |
||||
Method = query |
||||
``` |
||||
|
||||
获取APP内的所有书籍。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 获取书籍章节列表 |
||||
``` |
||||
URL = content://providerHost/book/chapter/query?url=xxx |
||||
Method = query |
||||
``` |
||||
|
||||
获取指定图书的章节列表。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
||||
|
||||
#### 获取书籍内容 |
||||
|
||||
``` |
||||
URL = content://providerHost/book/content/query?url=xxx&index=1 |
||||
Method = query |
||||
``` |
||||
|
||||
获取指定图书的第`index`章节的文本内容。 |
||||
用`Cursor.getString(0)`取出返回结果。 |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<string name="app_name">閲讀.D</string> |
||||
<string name="receiving_shared_label">閲讀·D·搜索</string> |
||||
</resources> |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<string name="app_name">閲讀.D</string> |
||||
<string name="receiving_shared_label">閲讀·D·搜索</string> |
||||
</resources> |
@ -0,0 +1,4 @@ |
||||
<resources> |
||||
<string name="app_name">阅读·D</string> |
||||
<string name="receiving_shared_label">阅读·D·搜索</string> |
||||
</resources> |
@ -1,4 +1,4 @@ |
||||
<resources> |
||||
<string name="app_name">悦读.debug</string> |
||||
<string name="receiving_shared_label">悦读.debug·搜索</string> |
||||
<string name="app_name">legado·D</string> |
||||
<string name="receiving_shared_label">legado·D·search</string> |
||||
</resources> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">阅读Pro</string> |
||||
|
||||
</resources> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">閱讀Pro</string> |
||||
|
||||
</resources> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">legadoPro</string> |
||||
|
||||
</resources> |
@ -0,0 +1,82 @@ |
||||
OGN5dS5jb20= |
||||
c2cwMC54eXo= |
||||
aXRyYWZmaWNuZXQuY29t |
||||
eGlhb3FpYW5nNTIw |
||||
MTIzeGlhb3FpYW5n |
||||
eGlhb3FpYW5neHM= |
||||
eGlhb3FpYW5nNTIw |
||||
MzM1eHM= |
||||
eGN4czk= |
||||
eGN4czUyMA== |
||||
c2h1YmFvYW4= |
||||
c2h1YmFvd2FuZzEyMw== |
||||
c2h1YmFvYW4= |
||||
aGFpdGFuZzEyMw== |
||||
eXV6aGFpd3VsYQ== |
||||
cG8xOA== |
||||
Ymwtbm92ZWw= |
||||
NXRucw== |
||||
c2hhb3NodWdl |
||||
amluamlzaHV3dQ== |
||||
NDJ3Zw== |
||||
eWlxdXNodQ== |
||||
c2h1YmFvd2FuZzEyMw== |
||||
M2hlYmFv |
||||
MzNoZWJhbw== |
||||
bHVvcWl1enc= |
||||
bXlzaHVnZQ== |
||||
c3NzeHN3 |
||||
eWl0ZQ== |
||||
Y3Vpd2VpanV1 |
||||
Y3Vpd2VpanV4cw== |
||||
Y3Vpd2VpanV4 |
||||
eGlhb3FpYW5nd3g= |
||||
YXN6dw== |
||||
YXN6dzY= |
||||
c2FuaGFveHM= |
||||
ODdzaHV3dQ== |
||||
NDh3eA== |
||||
bG9uZ3Rlbmcy |
||||
NnF3eA== |
||||
bG9uZ3Rlbmd4cw== |
||||
aGF4ZHU= |
||||
M3R3eA== |
||||
aGF4d3g1 |
||||
NjZsZXdlbg== |
||||
eGJhbnpodQ== |
||||
aGR5cA== |
||||
ZHliejk= |
||||
ZGl5aWJhbnpodTk= |
||||
ZGl5aWJhbnpodQ== |
||||
ZGl5aWJhbnpodTc= |
||||
YnoyMjI= |
||||
d29kZWFwaTAwMQ== |
||||
dGFuZ3poZWthbg== |
||||
YmF4aWFueHM= |
||||
eGlhb3NodW9zaGVuemhhbg== |
||||
ZGFtb2tl |
||||
emh3ZW5wZw== |
||||
eXV6aGFpZ2U= |
||||
d21wOA== |
||||
OXhpYW53ZW4= |
||||
bmFucmVudmlw |
||||
cmV5b28= |
||||
eWZ4aWFvc2h1b2U= |
||||
c2Fuaml1enc= |
||||
N3Fpbmc3 |
||||
cWR4aWFvc2h1bw== |
||||
Y2hpbmVzZXpq |
||||
MzlzaHViYW8= |
||||
a3l4czU= |
||||
NTZtcw== |
||||
bml1c2hh |
||||
bWt4czY= |
||||
MjIyMjJ4cw== |
||||
OTVkdXNodQ== |
||||
YmFuemh1MjI= |
||||
d3JsdHh0 |
||||
dHVkb3V0eHQ= |
||||
cm5neHM= |
||||
OTl3ZW5rdQ== |
||||
bGFvc2lqaXhz |
||||
ZnVzaHV6aGFpMQ== |
@ -0,0 +1,62 @@ |
||||
[ |
||||
{ |
||||
"id": 1598233029304, |
||||
"name": "度小美", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=0&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029305, |
||||
"name": "度小宇", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=1&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029306, |
||||
"name": "度逍遥", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=3&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029307, |
||||
"name": "度丫丫", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=4&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029308, |
||||
"name": "度小娇", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029309, |
||||
"name": "度米朵", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=103&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029310, |
||||
"name": "度博文", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=106&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029311, |
||||
"name": "度小童", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=110&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029312, |
||||
"name": "度小萌", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=111&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029313, |
||||
"name": "百度骚男", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=11&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029314, |
||||
"name": "百度评书", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=6&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
}, |
||||
{ |
||||
"id": 1598233029315, |
||||
"name": "百度主持", |
||||
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=9&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||
} |
||||
] |
@ -0,0 +1,26 @@ |
||||
[ |
||||
{ |
||||
"themeName": "典雅蓝", |
||||
"isNightTheme": false, |
||||
"primaryColor": "#03A9F4", |
||||
"accentColor": "#AD1457", |
||||
"backgroundColor": "#F5F5F5", |
||||
"bottomBackground": "#EEEEEE" |
||||
}, |
||||
{ |
||||
"themeName": "黑白", |
||||
"isNightTheme": true, |
||||
"primaryColor": "#303030", |
||||
"accentColor": "#E0E0E0", |
||||
"backgroundColor": "#424242", |
||||
"bottomBackground": "#424242" |
||||
}, |
||||
{ |
||||
"themeName": "A屏黑", |
||||
"isNightTheme": true, |
||||
"primaryColor": "#000000", |
||||
"accentColor": "#FFFFFF", |
||||
"backgroundColor": "#000000", |
||||
"bottomBackground": "#000000" |
||||
} |
||||
] |
After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 799 B After Width: | Height: | Size: 799 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
@ -0,0 +1,3 @@ |
||||
<!DOCTYPE html><html lang=en style="padding: 0;height:100%"><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="favicon.ico" /><![endif]--><title>Legado Bookshelf</title><link href=css/about.dbe575e1.css rel=prefetch><link href=css/detail.9ba76c69.css rel=prefetch><link href=js/about.59a63964.js rel=prefetch><link href=js/about~detail.1caf6ef5.js rel=prefetch><link href=js/detail.11777eca.js rel=prefetch><link href=css/app.e4c919b7.css rel=preload as=style><link href=css/chunk-vendors.ad4ff18f.css rel=preload as=style><link href=js/app.d7843716.js rel=preload as=script><link href=js/chunk-vendors.8dd9045a.js rel=preload as=script><link href=css/chunk-vendors.ad4ff18f.css rel=stylesheet><link href=css/app.e4c919b7.css rel=stylesheet><link rel=icon type=image/png sizes=32x32 href=img/icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=img/icons/favicon-16x16.png><link rel=manifest href=manifest.json><meta name=theme-color content=#4DBA87><meta name=apple-mobile-web-app-capable content=no><meta name=apple-mobile-web-app-status-bar-style content=default><meta name=apple-mobile-web-app-title content=yd-web-tool><link rel=apple-touch-icon href=img/icons/apple-touch-icon-152x152.png><link rel=mask-icon href=img/icons/safari-pinned-tab.svg color=#4DBA87><meta name=msapplication-TileImage content=img/icons/msapplication-icon-144x144.png><meta name=msapplication-TileColor content=#000000></head><style>body::-webkit-scrollbar { |
||||
display: none; |
||||
}</style><body style="margin: 0;height:100%"><noscript><strong>We're sorry but yd-web-tool doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.8dd9045a.js></script><script src=js/app.d7843716.js></script></body></html> |
@ -0,0 +1,74 @@ |
||||
self.__precacheManifest = (self.__precacheManifest || []).concat([ |
||||
{ |
||||
"revision": "a77097c019b699bc81ee", |
||||
"url": "css/about.dbe575e1.css" |
||||
}, |
||||
{ |
||||
"revision": "4d729c4b428d537ebd8d", |
||||
"url": "css/app.e4c919b7.css" |
||||
}, |
||||
{ |
||||
"revision": "3e91096748e0f4d6bb89", |
||||
"url": "css/chunk-vendors.ad4ff18f.css" |
||||
}, |
||||
{ |
||||
"revision": "8f2124417070a994ebbd", |
||||
"url": "css/detail.9ba76c69.css" |
||||
}, |
||||
{ |
||||
"revision": "535877f50039c0cb49a6196a5b7517cd", |
||||
"url": "fonts/element-icons.535877f5.woff" |
||||
}, |
||||
{ |
||||
"revision": "732389ded34cb9c52dd88271f1345af9", |
||||
"url": "fonts/element-icons.732389de.ttf" |
||||
}, |
||||
{ |
||||
"revision": "f9a3fb0e145017e166dd4d91d9280cc4", |
||||
"url": "fonts/iconfont.f9a3fb0e.woff" |
||||
}, |
||||
{ |
||||
"revision": "f39ecc1a1d2a1eff3aca8aadd818bb61", |
||||
"url": "fonts/popfont.f39ecc1a.ttf" |
||||
}, |
||||
{ |
||||
"revision": "6c094b6d4ae9404dbed273c41b06fae8", |
||||
"url": "fonts/shelffont.6c094b6d.ttf" |
||||
}, |
||||
{ |
||||
"revision": "b5c48bc1e1fe73212a31be704875b71f", |
||||
"url": "img/noCover.b5c48bc1.jpeg" |
||||
}, |
||||
{ |
||||
"revision": "ad9f43586bb9220e0df71ce8fad92d8b", |
||||
"url": "index.html" |
||||
}, |
||||
{ |
||||
"revision": "a77097c019b699bc81ee", |
||||
"url": "js/about.59a63964.js" |
||||
}, |
||||
{ |
||||
"revision": "2c81bd893f3a92f018d8", |
||||
"url": "js/about~detail.1caf6ef5.js" |
||||
}, |
||||
{ |
||||
"revision": "4d729c4b428d537ebd8d", |
||||
"url": "js/app.d7843716.js" |
||||
}, |
||||
{ |
||||
"revision": "3e91096748e0f4d6bb89", |
||||
"url": "js/chunk-vendors.8dd9045a.js" |
||||
}, |
||||
{ |
||||
"revision": "8f2124417070a994ebbd", |
||||
"url": "js/detail.11777eca.js" |
||||
}, |
||||
{ |
||||
"revision": "b46d04eb43bc31ca0f9f95121646440d", |
||||
"url": "manifest.json" |
||||
}, |
||||
{ |
||||
"revision": "b6216d61c03e6ce0c9aea6ca7808f7ca", |
||||
"url": "robots.txt" |
||||
} |
||||
]); |
@ -0,0 +1,2 @@ |
||||
User-agent: * |
||||
Disallow: |
@ -0,0 +1,34 @@ |
||||
/** |
||||
* Welcome to your Workbox-powered service worker! |
||||
* |
||||
* You'll need to register this file in your web app and you should |
||||
* disable HTTP caching for this file too. |
||||
* See https://goo.gl/nhQhGp
|
||||
* |
||||
* The rest of the code is auto-generated. Please don't update this file |
||||
* directly; instead, make changes to your Workbox build configuration |
||||
* and re-run your build process. |
||||
* See https://goo.gl/2aRDsh
|
||||
*/ |
||||
|
||||
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); |
||||
|
||||
importScripts( |
||||
"precache-manifest.78eb8adcb8f052b2a72d462abe0dc498.js" |
||||
); |
||||
|
||||
workbox.core.setCacheNameDetails({prefix: "yd-web-tool"}); |
||||
|
||||
self.addEventListener('message', (event) => { |
||||
if (event.data && event.data.type === 'SKIP_WAITING') { |
||||
self.skipWaiting(); |
||||
} |
||||
}); |
||||
|
||||
/** |
||||
* The workboxSW.precacheAndRoute() method efficiently caches and responds to |
||||
* requests for URLs in the manifest. |
||||
* See https://goo.gl/S9QRab
|
||||
*/ |
||||
self.__precacheManifest = [].concat(self.__precacheManifest || []); |
||||
workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); |
@ -0,0 +1,207 @@ |
||||
/* |
||||
* Copyright (C) 2020 w568w |
||||
*/ |
||||
package io.legado.app.api |
||||
|
||||
import android.content.ContentProvider |
||||
import android.content.ContentResolver |
||||
import android.content.ContentValues |
||||
import android.content.UriMatcher |
||||
import android.database.CharArrayBuffer |
||||
import android.database.ContentObserver |
||||
import android.database.Cursor |
||||
import android.database.DataSetObserver |
||||
import android.net.Uri |
||||
import android.os.Bundle |
||||
import com.google.gson.Gson |
||||
import io.legado.app.web.controller.BookshelfController |
||||
import io.legado.app.web.controller.SourceController |
||||
import io.legado.app.web.utils.ReturnData |
||||
import java.util.* |
||||
|
||||
/** |
||||
* Export book data to other app. |
||||
*/ |
||||
class ReaderProvider : ContentProvider() { |
||||
private enum class RequestCode { |
||||
SaveSource, SaveSources, SaveBook, DeleteSources, GetSource, GetSources, GetBookshelf, GetChapterList, GetBookContent |
||||
} |
||||
|
||||
private val postBodyKey = "json" |
||||
private val sMatcher by lazy { |
||||
UriMatcher(UriMatcher.NO_MATCH).apply { |
||||
"${context?.applicationInfo?.packageName}.readerProvider".also { authority -> |
||||
addURI(authority, "source/insert", RequestCode.SaveSource.ordinal) |
||||
addURI(authority, "sources/insert", RequestCode.SaveSources.ordinal) |
||||
addURI(authority, "book/insert", RequestCode.SaveBook.ordinal) |
||||
addURI(authority, "sources/delete", RequestCode.DeleteSources.ordinal) |
||||
addURI(authority, "source/query", RequestCode.GetSource.ordinal) |
||||
addURI(authority, "sources/query", RequestCode.GetSources.ordinal) |
||||
addURI(authority, "books/query", RequestCode.GetBookshelf.ordinal) |
||||
addURI(authority, "book/chapter/query", RequestCode.GetChapterList.ordinal) |
||||
addURI(authority, "book/content/query", RequestCode.GetBookContent.ordinal) |
||||
} |
||||
} |
||||
} |
||||
|
||||
override fun onCreate() = false |
||||
|
||||
override fun delete( |
||||
uri: Uri, |
||||
selection: String?, |
||||
selectionArgs: Array<String>? |
||||
): Int { |
||||
if (sMatcher.match(uri) < 0) return -1 |
||||
when (RequestCode.values()[sMatcher.match(uri)]) { |
||||
RequestCode.DeleteSources -> SourceController.deleteSources(selection) |
||||
else -> throw IllegalStateException( |
||||
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name |
||||
) |
||||
} |
||||
return 0 |
||||
} |
||||
|
||||
override fun getType(uri: Uri) = throw UnsupportedOperationException("Not yet implemented") |
||||
|
||||
override fun insert(uri: Uri, values: ContentValues?): Uri? { |
||||
if (sMatcher.match(uri) < 0) return null |
||||
when (RequestCode.values()[sMatcher.match(uri)]) { |
||||
RequestCode.SaveSource -> values?.let { |
||||
SourceController.saveSource(values.getAsString(postBodyKey)) |
||||
} |
||||
RequestCode.SaveBook -> values?.let { |
||||
BookshelfController.saveBook(values.getAsString(postBodyKey)) |
||||
} |
||||
RequestCode.SaveSources -> values?.let { |
||||
SourceController.saveSources(values.getAsString(postBodyKey)) |
||||
} |
||||
else -> throw IllegalStateException( |
||||
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name |
||||
) |
||||
} |
||||
return null |
||||
} |
||||
|
||||
override fun query( |
||||
uri: Uri, projection: Array<String>?, selection: String?, |
||||
selectionArgs: Array<String>?, sortOrder: String? |
||||
): Cursor? { |
||||
val map: MutableMap<String, ArrayList<String>> = HashMap() |
||||
uri.getQueryParameter("url")?.let { |
||||
map["url"] = arrayListOf(it) |
||||
} |
||||
uri.getQueryParameter("index")?.let { |
||||
map["index"] = arrayListOf(it) |
||||
} |
||||
return if (sMatcher.match(uri) < 0) null else when (RequestCode.values()[sMatcher.match(uri)]) { |
||||
RequestCode.GetSource -> SimpleCursor(SourceController.getSource(map)) |
||||
RequestCode.GetSources -> SimpleCursor(SourceController.sources) |
||||
RequestCode.GetBookshelf -> SimpleCursor(BookshelfController.bookshelf) |
||||
RequestCode.GetBookContent -> SimpleCursor(BookshelfController.getBookContent(map)) |
||||
RequestCode.GetChapterList -> SimpleCursor(BookshelfController.getChapterList(map)) |
||||
else -> throw IllegalStateException( |
||||
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name |
||||
) |
||||
} |
||||
} |
||||
|
||||
override fun update( |
||||
uri: Uri, values: ContentValues?, selection: String?, |
||||
selectionArgs: Array<String>? |
||||
) = throw UnsupportedOperationException("Not yet implemented") |
||||
|
||||
|
||||
/** |
||||
* Simple inner class to deliver json callback data. |
||||
* |
||||
* Only getString() makes sense. |
||||
*/ |
||||
private class SimpleCursor(data: ReturnData?) : Cursor { |
||||
|
||||
private val mData: String = Gson().toJson(data) |
||||
|
||||
override fun getCount() = 1 |
||||
|
||||
override fun getPosition() = 0 |
||||
|
||||
override fun move(i: Int) = true |
||||
|
||||
override fun moveToPosition(i: Int) = true |
||||
|
||||
override fun moveToFirst() = true |
||||
|
||||
override fun moveToLast() = true |
||||
|
||||
override fun moveToNext() = true |
||||
|
||||
override fun moveToPrevious() = true |
||||
|
||||
override fun isFirst() = true |
||||
|
||||
override fun isLast() = true |
||||
|
||||
override fun isBeforeFirst() = true |
||||
|
||||
override fun isAfterLast() = true |
||||
|
||||
override fun getColumnIndex(s: String) = 0 |
||||
|
||||
@Throws(IllegalArgumentException::class) |
||||
override fun getColumnIndexOrThrow(s: String): Int { |
||||
throw UnsupportedOperationException("Not yet implemented") |
||||
} |
||||
|
||||
override fun getColumnName(i: Int) = null as String? |
||||
|
||||
override fun getColumnNames() = arrayOf<String>() |
||||
|
||||
override fun getColumnCount() = 0 |
||||
|
||||
override fun getBlob(i: Int) = ByteArray(0) |
||||
|
||||
override fun getString(i: Int) = mData |
||||
|
||||
override fun copyStringToBuffer( |
||||
i: Int, |
||||
charArrayBuffer: CharArrayBuffer |
||||
) { |
||||
} |
||||
|
||||
override fun getShort(i: Int) = 0.toShort() |
||||
|
||||
|
||||
override fun getInt(i: Int) = 0 |
||||
|
||||
override fun getLong(i: Int) = 0L |
||||
|
||||
override fun getFloat(i: Int) = 0F |
||||
|
||||
override fun getDouble(i: Int) = 0.toDouble() |
||||
|
||||
override fun getType(i: Int) = 0 |
||||
|
||||
override fun isNull(i: Int) = false |
||||
|
||||
override fun deactivate() {} |
||||
override fun requery() = false |
||||
|
||||
override fun close() {} |
||||
override fun isClosed() = false |
||||
|
||||
override fun registerContentObserver(contentObserver: ContentObserver) {} |
||||
override fun unregisterContentObserver(contentObserver: ContentObserver) {} |
||||
override fun registerDataSetObserver(dataSetObserver: DataSetObserver) {} |
||||
override fun unregisterDataSetObserver(dataSetObserver: DataSetObserver) {} |
||||
override fun setNotificationUri(contentResolver: ContentResolver, uri: Uri) {} |
||||
|
||||
override fun getNotificationUri() = null as Uri? |
||||
|
||||
override fun getWantsAllOnMoveCalls() = false |
||||
|
||||
override fun setExtras(bundle: Bundle) {} |
||||
override fun getExtras() = null as Bundle? |
||||
|
||||
override fun respond(bundle: Bundle) = null as Bundle? |
||||
|
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
package io.legado.app.base |
||||
|
||||
import android.annotation.SuppressLint |
||||
import androidx.fragment.app.DialogFragment |
||||
import androidx.preference.* |
||||
import io.legado.app.ui.widget.prefs.EditTextPreferenceDialog |
||||
import io.legado.app.ui.widget.prefs.ListPreferenceDialog |
||||
import io.legado.app.ui.widget.prefs.MultiSelectListPreferenceDialog |
||||
|
||||
abstract class BasePreferenceFragment : PreferenceFragmentCompat() { |
||||
|
||||
private val dialogFragmentTag = "androidx.preference.PreferenceFragment.DIALOG" |
||||
|
||||
@SuppressLint("RestrictedApi") |
||||
override fun onDisplayPreferenceDialog(preference: Preference) { |
||||
|
||||
var handled = false |
||||
if (callbackFragment is OnPreferenceDisplayDialogCallback) { |
||||
handled = |
||||
(callbackFragment as OnPreferenceDisplayDialogCallback) |
||||
.onPreferenceDisplayDialog(this, preference) |
||||
} |
||||
if (!handled && activity is OnPreferenceDisplayDialogCallback) { |
||||
handled = (activity as OnPreferenceDisplayDialogCallback) |
||||
.onPreferenceDisplayDialog(this, preference) |
||||
} |
||||
|
||||
if (handled) { |
||||
return |
||||
} |
||||
|
||||
// check if dialog is already showing |
||||
if (parentFragmentManager.findFragmentByTag(dialogFragmentTag) != null) { |
||||
return |
||||
} |
||||
|
||||
val f: DialogFragment = when (preference) { |
||||
is EditTextPreference -> { |
||||
EditTextPreferenceDialog.newInstance(preference.getKey()) |
||||
} |
||||
is ListPreference -> { |
||||
ListPreferenceDialog.newInstance(preference.getKey()) |
||||
} |
||||
is MultiSelectListPreference -> { |
||||
MultiSelectListPreferenceDialog.newInstance(preference.getKey()) |
||||
} |
||||
else -> { |
||||
throw IllegalArgumentException( |
||||
"Cannot display dialog for an unknown Preference type: " |
||||
+ preference.javaClass.simpleName |
||||
+ ". Make sure to implement onPreferenceDisplayDialog() to handle " |
||||
+ "displaying a custom dialog for this Preference." |
||||
) |
||||
} |
||||
} |
||||
f.setTargetFragment(this, 0) |
||||
f.show(parentFragmentManager, dialogFragmentTag) |
||||
} |
||||
|
||||
|
||||
} |
@ -1,15 +1,19 @@ |
||||
package io.legado.app.constant |
||||
|
||||
import io.legado.app.help.AppConfig |
||||
import io.legado.app.utils.ColorUtils |
||||
|
||||
enum class Theme { |
||||
Dark, Light, Auto; |
||||
Dark, Light, Auto, Transparent; |
||||
|
||||
companion object { |
||||
fun getTheme(): Theme { |
||||
return if (AppConfig.isNightTheme) { |
||||
Dark |
||||
} else Light |
||||
} |
||||
fun getTheme() = |
||||
if (AppConfig.isNightTheme) Dark |
||||
else Light |
||||
|
||||
fun getTheme(backgroundColor: Int) = |
||||
if (ColorUtils.isColorLight(backgroundColor)) Light |
||||
else Dark |
||||
|
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
package io.legado.app.data.dao |
||||
|
||||
import androidx.lifecycle.LiveData |
||||
import androidx.room.* |
||||
import io.legado.app.data.entities.HttpTTS |
||||
|
||||
@Dao |
||||
interface HttpTTSDao { |
||||
|
||||
@get:Query("select * from httpTTS order by name") |
||||
val all: List<HttpTTS> |
||||
|
||||
@Query("select * from httpTTS order by name") |
||||
fun observeAll(): LiveData<List<HttpTTS>> |
||||
|
||||
@get:Query("select count(*) from httpTTS") |
||||
val count: Int |
||||
|
||||
@Query("select * from httpTTS where id = :id") |
||||
fun get(id: Long): HttpTTS? |
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
fun insert(vararg httpTTS: HttpTTS) |
||||
|
||||
@Delete |
||||
fun delete(vararg httpTTS: HttpTTS) |
||||
|
||||
@Update |
||||
fun update(vararg httpTTS: HttpTTS) |
||||
|
||||
} |
@ -0,0 +1,39 @@ |
||||
package io.legado.app.data.dao |
||||
|
||||
import androidx.room.* |
||||
import io.legado.app.data.entities.ReadRecord |
||||
import io.legado.app.data.entities.ReadRecordShow |
||||
|
||||
@Dao |
||||
interface ReadRecordDao { |
||||
|
||||
@get:Query("select * from readRecord") |
||||
val all: List<ReadRecord> |
||||
|
||||
@get:Query("select bookName, sum(readTime) as readTime from readRecord group by bookName order by bookName") |
||||
val allShow: List<ReadRecordShow> |
||||
|
||||
@get:Query("select sum(readTime) from readRecord") |
||||
val allTime: Long |
||||
|
||||
@Query("select sum(readTime) from readRecord where bookName = :bookName") |
||||
fun getReadTime(bookName: String): Long? |
||||
|
||||
@Query("select readTime from readRecord where androidId = :androidId and bookName = :bookName") |
||||
fun getReadTime(androidId: String, bookName: String): Long? |
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
fun insert(vararg readRecord: ReadRecord) |
||||
|
||||
@Update |
||||
fun update(vararg record: ReadRecord) |
||||
|
||||
@Delete |
||||
fun delete(vararg record: ReadRecord) |
||||
|
||||
@Query("delete from readRecord") |
||||
fun clear() |
||||
|
||||
@Query("delete from readRecord where bookName = :bookName") |
||||
fun deleteByName(bookName: String) |
||||
} |