diff --git a/app/cronetlib/cronet_api.jar b/app/cronetlib/cronet_api.jar index 9ed47b0a7..6e6fef274 100644 Binary files a/app/cronetlib/cronet_api.jar and b/app/cronetlib/cronet_api.jar differ diff --git a/app/cronetlib/cronet_impl_common_java.jar b/app/cronetlib/cronet_impl_common_java.jar index a8a0e6a86..05c61faad 100644 Binary files a/app/cronetlib/cronet_impl_common_java.jar and b/app/cronetlib/cronet_impl_common_java.jar differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f1624fe82..6c95c79ce 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -293,6 +293,10 @@ + + ? +putLoginHeader(header: String) +removeLoginHeader() +setVariable(variable: String?) +getVariable(): String? +AnalyzeUrl相关函数,js中通过java.调用 +initUrl() //重新解析url,可以用于登录检测js登录后重新解析url重新访问 +getHeaderMap().putAll(source.getHeaderMap(true)) //重新设置登录头 +getStrResponse( jsStr: String? = null, sourceRegex: String? = null) //返回访问结果,文本类型,书源内部重新登录后可调用此方法重新返回结果 +getResponse(): Response //返回访问结果,网络朗读引擎采用的是这个,调用登录后在调用这方法可以重新访问,参考阿里云登录检测 ``` * 发现url格式 diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 3476d2c02..1059ac467 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -11,6 +11,12 @@ * 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。 * 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源! +**2022/04/05** + +* 更新cronet: 100.0.4896.79 +* 添加所有书签 +* 添加批量换源 + **2022/03/31** * 添加java.importScript,详情见js帮助文档 @@ -205,653 +211,4 @@ eval(String(java.cacheFile(url))) **2022/01/01** * 修复本地txt问题,不在拷贝到私有目录,可以正常打开 -* 优化txt目录识别,取目录数量最多的规则 - -**2021/12/28** - -* 用阅读打开本地朗读引擎文件和主体配置文件也可以导入 -* 缓存图片采用多线程 -* 本地书籍不在拷贝到私有目录,有权限的会直接打开,没权限的自己选择文件夹保存 - -**2021/12/19** - -* 修复全面屏手势会触发翻页的bug -* js添加java.logType(*),打印变量类型,方便调试时查看 -* 修复从发现中打开书籍是会打开其它书源书籍的bug -* 全文搜索增加跳转上一个下一个的功能 by Jason Yao -* post可以正确识别contentType - -**2021/12/10** - -* 朗读出错不弹出朗读界面的时候可以长按朗读按钮进入朗读界面切换朗读引擎,这个有很多人不知道 -* 修复cronet访问出错时应用崩溃的bug -* 修复一些epub目录不全或内容不全的问题 -* 修复横屏双页时文字选择的问题 -* 电脑硬盘坏了还好资料恢复出来了,还是要经常备份比较好 - -**2021/11/27** - -* 更新到SDK31,android 12 -* 修复在线朗读引擎新建会替换之前已有的bug -* 修复目录界面自动跳转到顶部bug -* 修复阿里云在线朗读引擎模板中获取时间的兼容性问题 - -**2021/11/20** - -* 修复部分平板双页问题 -* 修复书源太多不能导出和备份的问题 -* 给txt目录规则添加了一个入口,在书源管理的菜单里面 - -**2021/11/13** - -* 修复没有目录时进入阅读界面不自动更新目录的bug -* 使用系统文件夹选择器出错时自动打开应用文件夹选择器,部分系统文件夹选择器被阉割了 - -**2021/11/02** - -* 修复朗读错误时提示不消失的bug -* 修复滚动阅读选择文字错位bug by DuShuYuan -* 朗读语速调节添加微调按钮 - -**2021/10/24** - -* 修复夜间模式不随系统变化的bug - -**2021/10/22** - -* 修复封面 -* 添加全局字体大小设置 -* 导入源和规则时可以先编辑再导入 - -**2021/10/21** - -* 修复自定义封面会因为图片太大崩溃 -* 修复play版本一个会引起崩溃的bug - -**2021/10/17** - -* 修复朗读时可能会崩溃的bug - -**2021/10/16** - -* 再次修复朗读卡住问题 -* 导入书单改为多线程 -* 修复其它一些bug - -**2021/10/14** - -* 修复遇到一些存标点段朗读出错后不继续的问题 -* 朗读出错记录错误日志,现在很多界面的菜单里都可以打开日志 - -**2021/10/10** - -* 阿里云语音自动登录 -* 修复一些bug -* 优化阿里云登录,需重新登录 - -``` -source登录相关方法,可在js内通过source.调用,可以参考阿里云语音登录 -login() -getHeaderMap(hasLoginHeader: Boolean = false) -getLoginHeader(): String? -getLoginHeaderMap(): Map? -putLoginHeader(header: String) -removeLoginHeader() -setVariable(variable: String?) -getVariable(): String? -AnalyzeUrl相关函数,js中通过java.调用 -initUrl() //重新解析url,可以用于登录检测js登录后重新解析url重新访问 -getHeaderMap().putAll(source.getHeaderMap(true)) //重新设置登录头 -getStrResponse( jsStr: String? = null, sourceRegex: String? = null) //返回访问结果,文本类型,书源内部重新登录后可调用此方法重新返回结果 -getResponse(): Response //返回访问结果,网络朗读引擎采用的是这个,调用登录后在调用这方法可以重新访问,参考阿里云登录检测 -``` - -**2021/10/07** - -1. 修复阅读界面长按菜单阻挡选择bug -2. 添加订阅源api - -**2021/10/05** - -1. 优化阅读界面导航栏 -2. 规则添加代码高亮 -3. web写源添加订阅源 -4. httpTts朗读添加登录功能 - -``` -返回语音之前加入了检测是否登录传入result为okhttp的Response,里面有headers和body,检测是否登录的js需返回正确的Response -``` - -**2021/10/02** - -1. 紧急修复弹出框崩溃bug -2. 修复字体变粗后不能变回的bug -3. 修复底部对齐有时无效的bug - -* 不要嫌更新得频繁,这是因为最近新加的功能比较多,出bug很正常,而且我是一个人写软件,没有测试人员,只有发出来大家一起找bug了,遇到bug及时反馈,能修复的我都会在第一时间修复 - -**2021/10/01** - -1. 默认封面名称显示全 -2. 发现js错误时可以查看错误详情 -4. 修复rss标题显示url的问题 -5. 长按正文网址可以选择是否外部浏览器打开,会记住选择 -6. 添加书源操作按钮,编辑书源移到里面,增加网址点击区域包括书名,更容易点击 -7. 优化内置浏览器 -8. 其它一些优化 - -**2021/09/29** - -1. 修复阅读界面导航栏挡住内容的bug -2. 修复webView=ture是自动跳转移动网站的bug -3. 导出添加进度条 - -**2021/09/28** - -1. 添加横屏双页模式 - -**2021/09/27** - -1. 非Play版本内置更新检测和下载,目前从github检测并下载, 不会自动提醒需手动检测, 可以关注公众号,比较重要的更新会在公众号发布然后可以在软件内更新 -2. js添加java.webView(html: String?, url: String?, js: String?): String? -3. 修复一些bug - -**2021/09/22** - -1. 修复在线朗读遇到单独......崩溃的问题 -2. 有人提到在线朗读能及时翻页了,本地行不行,这个是要靠本地的tts支持的,我目前用的谷歌文字转语音就是支持的,其它的我不太清楚 - -**2021/09/21** - -1. 阅读界面区域设置添加朗读上一段和朗读下一段 -2. 在线朗读采用平均速度计算及时翻页 -3. 修复听书定时问题 -4. 阅读小标题也使用替换 - -**2021/09/20** - -1. 修复在线朗读跳段的bug -2. 优化默认封面,添加显示书名作者的配置, 后面会添加书名和作者大小位置配置 - -**2021/09/18** - -1. 朗读可以选择非默认tts -2. 其它一些优化和bug修复 - -**2021/09/16** - -1. 优化正文重复标题的去除,必须包含标题且标题后面有空格或换行才会去除,防止误删 - -```^(\s|\p{P}|${name})*${title}(\s|\p{P})+``` - -**2021/09/15** - -1. 修复因标题加入替换和简繁转换导致的缩进问题 -2. 如果出现标题不显示是净化规则的问题,可以先关闭净化 - -**2021/09/14** - -1. 书架菜单添加了日志,更新失败的和下载失败的信息会显示在里面 -2. 书源添加校验关键字,有校验关键字的书源用此关键字校验 -3. 目录添加购买标识规则 -4. 正文标题使用替换,简繁转换,正文中书名,标题开头的自动去重 -5. 其它一些优化 - -**2021/09/08** - -1. 优化离线缓存 -2. 听书界面添加登录菜单,和拷贝播放url -3. 详情页添加设置源变量和书籍变量 -4. 订阅添加登录菜单,添加设置源变量 - -**2021/09/06** - -1. 采用exoPlayer播放音频,支持更多格式 -2. 替换不再阻塞 -3. 修复详情页初始化:规则bug -4. 书源内的并发率生效,两种格式 - * 时间 格式: 如 500, 访问间隔500毫秒 - * 次数/时间 格式: 如 5/60000, 每分钟最多访问5次 - -5. url参数添加js, 和webJs参数,js参数传入url返回新的url, webJs参数在webView内执行直到返回不为空,和正文规则webJs一样 -6. 重写离线缓存 - -**2021/09/01** - -1. 可以直接导出为链接,方便分享 -2. 修复一些bug - -**2021/08/28** - -1. 发现界面添加登录菜单 -2. 优化调试界面,预设搜索项可以点击 -3. 修复再没有webDav恢复时恢复按钮没反应的bug -4. 自动阅读的设置改为选择翻页动画 - -**2021/08/27** - -1. 修复导入书源问题 -2. 合并cornet版本,添加cornet开关 -3. 详情也选择分组后自动加入书架 -4. 书源管理可以筛选有登录url的书源,分组需登录 -5. 修复定时加快的问题 -7. 修复其它一些小bug - -**2021/08/24** - -1. 修复bug -2. 可以加载证书过期网站的图片 -3. 修复书源不兼容老版本的问题 -4. 书源添加登录ui,和登录检测配置,稍后会给出示例,可以用来制作一些采用token登录的源,稍后会给出示例 -5. 修复web阅读进度没有同步到webDav的问题 - -**2021/08/21** - -1. 阅读时自动更新最新章节 -2. 朗读添加媒体按键配置 -3. 修复rss列表界面分类往回切换时没有数据的bug -4. 修复订阅分类往回切换时不显示内容的bug -5. 导入书源防止非json格式导入 -6. 校验书源显示详细信息 by h11128 -7. 其它一些优化 - -**2021/08/13** - -1. web传书可以使用 -2. 修复一些bug - -**2021/08/09** - -1. 修复选择文字不能选择单个文字的bug -2. 分组可选择封面 - -**2021/08/08** - -1. 背景图片添加模糊设置 -2. 书籍信息界面添加置顶操作 -3. 自动翻页时屏幕常亮 -4. 字典:中文使用百度汉语字典,英文使用海词字典。 by ag2s20150909 -5. 导入规则时可以选择添加分组还是替换分组 - -**2021/08/02** - -1. 换源界面功能添加:置顶,置底,删除 by h11128 -2. Cronet:优化 by ag2s20150909 -3. 优化自动翻页 by jiuZhouWorlds -4. 封面设置移到主题里面,白天和夜间可分别设置 - -**2021/08/01** - -1. 为webService添加快捷操作 -2. 规则内替换使用正则错误时自动切换为不使用正则 -3. 优化Cronet -4. 阅读界面菜单显示的时候停止按键翻页和自动阅读 -5. 切换后台停止自动阅读 - -**2021/07/29** - -1. 修复每次更新都重新导入text规则的bug -2. RSS阅读页添加刷新按钮以应对页面内容过期失效的BUG by JiuZhouWorlds -3. 规则内替换使用正则报错时自动使用非正则替换 - -**2021/07/27** - -1. 修复bug -2. web使用api获取封面,不会再出现没有封面的情况 -3. 阅读亮度手动调节分别记住白天和夜间模式 -4. legado://import/auto?src={url}, 自动识别导入类型 -5. 一些优化并更新了一下web首页,感谢沚水, 传书暂时还不好用 - -**2021/07/22** - -1. 非关键规则添加try防止报错中断解析 -2. 添加获取封面的api -3. 获取正文api使用替换规则 -4. 添加一个ronet版本,网络访问使用Chromium内核 -5. web书架增加【最近一次更新书籍信息的时间】 -6. 采用Flow替换LiveData,优化资源使用 -7. 统一网络一键导入路径legado://import/{path}?src={url} - -* path: bookSource,rssSource,replaceRule,textTocRule,httpTTS,theme,readConfig -* 添加了txt小说规则,在线朗读引擎,主题,排版 的一键导入支持,老url依然可用 - -8. 替换规则管理添加置顶所选和置底所选 - -**2021/07/16** - -1. js扩展函数添加删除本地文件方法 -2. js扩展函数对于文件的读写删操作都是相对路径,只能操作阅读缓存内的文件,/android/data/{package}/cache/... - -**2021/07/15** - -1. 添加js函数来修复开启js沙箱后某些书源失效。by ag2s20150909 - -```kotlin -/** - * 获取网络zip文件里面的数据 - * @param url zip文件的链接 - * @param path 所需获取文件在zip内的路径 - * @return zip指定文件的数据 - */ -fun getZipStringContent(url: String, path: String): String - -/** - * 获取网络zip文件里面的数据 - * @param url zip文件的链接 - * @param path 所需获取文件在zip内的路径 - * @return zip指定文件的数据 - */ -fun getZipByteArrayContent(url: String, path: String): ByteArray? -``` - -* web服务添加一个导航页 - -**2021/07/11** - -1. 开启JS沙箱限制 - -* 禁止在js里exec运行命令 -* 禁止在js里通过geClass反射 -* 禁止在js里创建File对象 -* 禁止在js里获取Packages scope - -2. 优化并修复bug - -**2021/07/10** - -1. 阅读界面长按菜单改回原来样式 -2. 解决导入书源时重命名分组和保留名称冲突的问题 - -**2021/07/09** - -1. 发现url添加json格式, 支持设置标签样式 - -* 样式属性可以搜索 [FleboxLayout子元素支持的属性介绍](https://www.jianshu.com/p/3c471953e36d) -* 样式属性可省略,有默认值 - -**2021/07/07** - -1. 默认规则新增类似`jsonPath`的索引写法 by bushixuanqi - -* 格式形如 `[index,index, ...]` 或 `[!index,index, ...]` 其中`[!`开头表示筛选方式为排除,`index`可以是单个索引,也可以是区间。 -* 区间格式为 `start:end` 或 `start:end:step`,其中`start`为`0`可省略,`end`为`-1`可省略。 -* 索引、区间两端、区间间隔都支持负数 -* 例如 `tag.div[-1, 3:-2:-10, 2]` -* 特殊用法 `tag.div[-1:0]` 可在任意地方让列表反向 - -2. 允许索引作为@分段后每个部分的首规则,此时相当于前面是`children` - -* `head@.1@text` 与 `head@[1]@text` 与 `head@children[1]@text` 等价 - -3. 添加Umd格式支持 by ag2s20150909 -4. 修复web页面按键重复监听的bug -5. 亮度条往中间移了一点,防止误触 -6. 添加内置字典 - -**2021/06/29** - -* 修复html格式化bug -* 订阅界面webView支持css prefers-color-scheme: dark 查询,需webView v76或更高版本 -* 如webView低于v76可以用js调用activity.isNightTheme()来获取当前是否暗模式 -* 修复一些书籍导出epub失败 by ag2s20150909 - -**2021/06/22** - -* 修复隐藏未读设置不生效的bug -* 修复系统字体大小选择大时导入界面按钮显示不全的bug -* 修复听书从后台打开时不对的bug - -**2021/06/20** - -* viewPager2 改回 viewPager -* 添加配置导入文件规则功能 by bushixuanqi -* 文件夹分组样式优化(未完成) -* epub支持外部模板 -* 修复一些bug - -**2021/06/06** - -* 添加自定义导出文件名 -* 添加书架文件夹分组样式,未完成 -* viewPager2 3层嵌套有问题,书架换回viewPager - -**2021/05/29** - -* 谷歌版可使用外部epub模板 -* Asset文件夹下二级以内目录全文件读取,Asset->文件夹->文件 -* epub元数据修改,使修改字体只对正文生效 -* 修复epub模板文件的排序问题 -* epub可自定义模板,模板路径为书籍导出目录的Asset文件夹,[模板范例](https://wwa.lanzoux.com/ibjBspkn05i) - -``` -Asset中里面必须有Text文件夹,Text文件夹里必须有chapter.html,否则导出正文会为空 -chapter.html的关键字有{title}、{content} -其他html文件的关键字有{name}、{author}、{intro}、{kind}、{wordCount} -``` - -**2021/05/24** - -* 反转目录后刷新内容 -* 修复上下滑动会导致左右切换问题 -* 精确搜索增加包含关键词的,比如搜索五行 五行天也显示出来, 五天行不显示 - -**2021/05/21** - -* 添加反转目录功能 -* 修复分享bug -* 详情页添加登录菜单 -* 添加发现界面隐藏配置 - -**2021/05/16** - -* 添加总是使用默认封面配置 -* 添加一种语言 ptbr translation by mezysinc -* epublib 修bug by ag2s20150909 - -**2021/05/08** - -* 预下载章节可调整数目 -* 修复低版本Android使用TTS闪退。 by ag2s20150909 -* 修复WebDav报错 -* 优化翻页动画点击翻页 - -**2021/05/06** - -* 修复bug -* url参数添加重置次数,retry -* 修改默认tts, 手动导入 -* 升级android studio - -**2021/04/30** - -* epub插图,epublib优化,图片解码优化,epub读取导出优化。by ag2s20150909 -* 添加高刷设置 -* 其它一些优化 -* pro版本被play商店下架了,先把pro设置图片背景的功能开放到所有版本,使用pro版本的可以使用备份恢复功能切换最新版本 - -**2021/04/16** - -* 去掉google统计,解决华为手机使用崩溃的bug -* 添加规则订阅时判断重复提醒 -* 添加恢复预设布局的功能, 添加一个微信读书布局作为预设布局 - -**2021/04/08** - -* 缓存时重新检查并缓存图片 -* 订阅源调试添加源码查看 -* web调试不输出源码 -* 修复bug -* 换源优化 --- by ag2s20150909 -* 修复localBook获取书名作者名的逻辑 -* 修复导出的epub的标题文字过大的bug -* 优化图片排版 - -**2021/04/02** - -* 修复bug -* 书源调试添加源码查看 -* 添加导出epub by ag2s20150909 -* 换源添加是否校验作者选项 - -**2021/03/31** - -* 优化epubLib by ag2s20150909 -* 升级库,修改弃用方法 -* tts引擎添加导入导出功能 - -**2021/03/23** - -* 修复繁简转换“勐”“十”问题。使用了剥离HanLP简繁代码的民间库。APK减少6M左右 -* js添加一个并发访问的方法 java.ajaxAll(urlList: Array) 返回 Array -* 优化目录并发访问 -* 添加自定义epublib,支持epub v3解析目录。by ag2s20150909 - -**2021/03/19** - -* 修复图片地址参数缺少的bug -* 修复更改替换规则时多次重新加载正文导致朗读多次停顿的bug -* 修复是否使用替换默认值修改后不及时生效的bug -* 修复繁简转换“勐”“十”问题。使用了剥离HanLP简繁代码的民间库。APK减少6M左右 by hoodie13 -* 百度tsn改为tts - -**2021/03/15** - -* 优化图片TEXT样式显示 -* 图片url在解析正文时就拼接成绝对url -* 修复一些bug - -**2021/03/08** - -* 阅读页面停留10分钟之后自动备份进度 -* 添加了针对中文的断行排版处理-by hoodie13, 需要再阅读界面设置里手动开启 -* 添加朗读快捷方式 -* 优化Epub解析 by hoodie13 -* epub书籍增加cache by hoodie13 -* 修复切换书籍或者章节时的断言崩溃问题。看漫画容易复现。 by hoodie13 -* 修正增加书签alert的正文内容较多时,确定键溢出屏幕问题 by hoodie13 -* 图片样式添加TEXT, 阅读界面菜单里可以选择图片样式 - -**2021/02/26** - -* 添加反转内容功能 -* 更新章节时若无目录url将自动加载详情页 -* 添加变量nextChapterUrl -* 订阅跳转外部应用时提示 -* 修复恢复bug -* 详情页拼接url改为重定向后的地址 -* 不重复解析详情页 - -**2021/02/21** - -* 下一页规则改为在内容规则之后执行 -* 书籍导出增加编码设置和导出文件夹设置,使用替换设置 -* 导入源添加等待框 -* 修复一些崩溃bug - -**2021/02/16** - -* 修复分享内容不对的bug -* 优化主题颜色,添加透明度 -* rss分类url支持js -* 打开阅读时同步阅读进度 - -**2021/02/09** - -* 修复分组内书籍数目少于搜索线程数目,会导致搜索线程数目变低 -* 修复保存书源时不更新书源时间的bug -* 订阅添加夜间模式,需启用js,还不是很完善 -* 优化源导入界面 - -**2021/01/18** - -* 增加三星 S Pen 支持 by [dacer](https://github.com/dacer) -* 订阅添加阅读下载,可以从多个渠道下载 -* 解决文件下载异常,在线语音可正常播放 by [Celeter](https://github.com/Celeter) -* 更新默认在线朗读库, 默认id小于0方便下次更新时删除旧数据, 有重复的自己删除 -* 导入导出书单 -* 其它一些优化 - -**2020/12/27** - -* 订阅添加搜索和分组 -* 修复部分手机状态栏bug -* 单url订阅支持内容规则和样式 - -**2020/12/09** - -* 修复bug -* 优化中文排序 -* 优化编码识别 -* 选择文字时优先选词 -* 优化进度同步,进入书籍时同步,每次同步单本书,减少同步文件大小 - -**2020/11/18** - -* 优化导航栏 -* js添加java.log(msg: String)用于调试时输出消息 -* js添加cookie变量,方法见io.legado.app.help.http.api.CookieManager -* js添加cache变量,可以用来存储token之类的临时值,可以设置保存时间,方法见io.legado.app.help.CacheManager -* 需要token的网站可以用js来写了,比如阿里tts - -**2020/11/15** - -* 正文规则添加字体规则,返回ByteArray -* js添加方法: - -``` -base64DecodeToByteArray(str: String?): ByteArray? -base64DecodeToByteArray(str: String?, flags: Int): ByteArray? -``` - -**2020/11/07** - -* 详情页菜单添加拷贝URL -* 解决一些书名太长缓存报错的bug -* 添加备份搜索记录 -* 替换编辑界面添加正则学习教程 -* 去除解析目录时拼接相对url,提升解析速度 -* 自动分段优化 by [tumuyan](https://github.com/tumuyan) -* web支持图片显示 by [六月](https://github.com/Celeter) - -**2020/10/24** - -* 修复选择错误的bug -* 修复长图最后一张不能滚动的bug -* js添加java.getCookie(sourceUrl:String, key:String? = null)来获取登录后的cookie - by [AndyBernie](https://github.com/AndyBernie) - -``` -java.getCookie("http://baidu.com", null) => userid=1234;pwd=adbcd -java.getCookie("http://baidu.com", "userid") => 1234 -``` - -* 修复简繁转换没有处理标题 -* 每本书可以单独设置翻页动画,在菜单里 -* 添加重新分段功能,针对每本书,在菜单里,分段代码来自[tumuyan](https://github.com/tumuyan) - -**2020/10/07** - -* 更新时预下载10章 -* 支持更多分组 -* url添加js参数,解析url时执行,可在访问url时处理url,例 - -``` -https://www.baidu.com,{"js":"java.headerMap.put('xxx', 'yyy')"} -https://www.baidu.com,{"js":"java.url=java.url+'yyyy'"} -``` - -**2020/09/29** - -* 增加了几个方法用于处理文件 by [Celeter](https://github.com/Celeter) - -``` -//文件下载,content为十六进制字符串,url用于生成文件名,返回文件路径 -downloadFile(content: String, url: String): String -//文件解压,zipPath为压缩文件路径,返回解压路径 -unzipFile(zipPath: String): String -//文件夹内所有文件读取 -getTxtInFolder(unzipPath: String): String -``` - -* 增加type字段,返回16进制字符串,例:`https://www.baidu.com,{"type":"zip"}` -* 底部操作栏阴影跟随设置调节 +* 优化txt目录识别,取目录数量最多的规则 \ No newline at end of file diff --git a/app/src/main/assets/web/bookshelf/css/detail.c24d2b34.css b/app/src/main/assets/web/bookshelf/css/detail.01ad55b1.css similarity index 79% rename from app/src/main/assets/web/bookshelf/css/detail.c24d2b34.css rename to app/src/main/assets/web/bookshelf/css/detail.01ad55b1.css index e228b1d1c..ce21f267f 100644 --- a/app/src/main/assets/web/bookshelf/css/detail.c24d2b34.css +++ b/app/src/main/assets/web/bookshelf/css/detail.01ad55b1.css @@ -1 +1 @@ -@charset "UTF-8";@font-face{font-family:FZZCYSK;src:local("☺"),url(../fonts/popfont.f39ecc1a.ttf);font-style:normal;font-weight:400}.cata-wrapper[data-v-0aacaab8]{margin:-16px;padding:18px 0 24px 25px}.cata-wrapper .title[data-v-0aacaab8]{font-size:18px;font-weight:400;font-family:FZZCYSK;margin:0 0 20px 0;color:#ed4259;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;border-bottom:1px solid #ed4259}.cata-wrapper .data-wrapper[data-v-0aacaab8]{height:300px;overflow:auto}.cata-wrapper .data-wrapper .cata[data-v-0aacaab8]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.cata-wrapper .data-wrapper .cata .selected[data-v-0aacaab8]{color:#eb4259}.cata-wrapper .data-wrapper .cata .log[data-v-0aacaab8]{width:50%;height:40px;cursor:pointer;float:left;font:16px/40px PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,Microsoft YaHei,sans-serif}.cata-wrapper .data-wrapper .cata .log .log-text[data-v-0aacaab8]{margin-right:26px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.cata-wrapper .night[data-v-0aacaab8] .log{border-bottom:1px solid #666}.cata-wrapper .day[data-v-0aacaab8] .log{border-bottom:1px solid #f2f2f2}@media screen and (max-width:500px){.cata-wrapper .data-wrapper .cata .log[data-v-0aacaab8]{width:100%}}@font-face{font-family:iconfont;src:url(../fonts/iconfont.f9a3fb0e.woff) format("woff")}[data-v-65e7f0f4] .iconfont,[data-v-65e7f0f4] .moon-icon{font-family:iconfont;font-style:normal}.settings-wrapper[data-v-65e7f0f4]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;margin:-13px;height:300px;text-align:left;padding:40px 0 40px 24px;background:#ede7da url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyBAMAAADsEZWCAAAAD1BMVEX48dr48Nf58tv379X17NJtIBxUAAACFUlEQVQ4y1XRUZakMAgF0Af2AiDWApDZgHZqAV1nZv9rGh7Rj7Y8McUFEg1wvcMESMNVD/neU8Xcaz7nYYkYlYO6Ti82PBI4BvIEg1aj3wKwRvIMgZsUy5LdhCawPFh1sZs4SrlyN9fQKpv8s5dgZ2eLyqqJiu+WkCmUEybXkm3INS01WAiv0PapJ0CZc0SJQUzcWnZYbOOY20iFD8Bk+/j2A3wNxH7GdShFYS5ff237kXh9I9zSkQmIAhOsOSVfJ6DIXTMDaPnzkRJ92S1BQQmXl5LdirgRLLDdcYqcGPwe3QN4xCBiGNbrqq9wpW1XCecChwaQdVOsRDpPCpeoolPdxeXp3WNB9PHVzWBHlygy4NJCCrFHREv6bDt0VGwJZASkpONmm1UseGeFKAQexgaAkrfYWl3AGxWOLL2AIMBNbCXpktmS3k3vHeYjGCPBa43wJTurO3ZFVpQSJdAZGLoHTyk1upkjxMEaIxum3iIARcCa5kSkFAW5fi1mUlL9eyOsaanFmOMruwvEdE3ZYzsRSzo5ewRLXyVPPEvknt8ij4DvCg2O7xOgBCUprEzV4z1WekSpUgI8DT2mrnSOXKRfQavwuKA1F+tFnMKdJSUpMA7wQAifWRkMgjUKKZE4lBl6MCM4B1pq1P4uIjDE6Pq6rL0FnW1nIFmta5vrSvq/Ch4tpqG/ZNyyWa5jZPktq81eYv8Bt5s4iFITOp4AAAAASUVORK5CYII=) repeat}.settings-wrapper .settings-title[data-v-65e7f0f4]{font-size:18px;line-height:22px;margin-bottom:28px;font-family:FZZCYSK;font-weight:400}.settings-wrapper .setting-list ul[data-v-65e7f0f4]{list-style:none outside none;margin:0;padding:0}.settings-wrapper .setting-list ul li[data-v-65e7f0f4]{list-style:none outside none}.settings-wrapper .setting-list ul li i[data-v-65e7f0f4]{font:12px/16px PingFangSC-Regular,-apple-system,Simsun;display:inline-block;min-width:48px;margin-right:16px;vertical-align:middle;color:#666}.settings-wrapper .setting-list ul li .theme-item[data-v-65e7f0f4]{line-height:32px;width:34px;height:34px;margin-right:16px;margin-top:5px;border-radius:100%;display:inline-block;cursor:pointer;text-align:center;vertical-align:middle}.settings-wrapper .setting-list ul li .theme-item .iconfont[data-v-65e7f0f4]{display:none}.settings-wrapper .setting-list ul li .selected[data-v-65e7f0f4]{color:#ed4259}.settings-wrapper .setting-list ul li .selected .iconfont[data-v-65e7f0f4]{display:inline}.settings-wrapper .setting-list ul .font-list[data-v-65e7f0f4]{margin-top:28px}.settings-wrapper .setting-list ul .font-list .font-item[data-v-65e7f0f4]{width:78px;height:34px;cursor:pointer;margin-right:16px;border-radius:2px;text-align:center;vertical-align:middle;display:inline-block;font:14px/34px PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,Microsoft YaHei,sans-serif}.settings-wrapper .setting-list ul .font-list .font-item[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .font-list .selected[data-v-65e7f0f4]{color:#ed4259;border:1px solid #ed4259}.settings-wrapper .setting-list ul .font-size[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width[data-v-65e7f0f4]{margin-top:28px}.settings-wrapper .setting-list ul .font-size .resize[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize[data-v-65e7f0f4]{display:inline-block;width:274px;height:34px;vertical-align:middle;border-radius:2px}.settings-wrapper .setting-list ul .font-size .resize span[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize span[data-v-65e7f0f4]{width:89px;height:34px;line-height:34px;display:inline-block;cursor:pointer;text-align:center;vertical-align:middle}.settings-wrapper .setting-list ul .font-size .resize span em[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize span em[data-v-65e7f0f4]{font-style:normal}.settings-wrapper .setting-list ul .font-size .resize .less[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .font-size .resize .more[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .read-width .resize .less[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .read-width .resize .more[data-v-65e7f0f4]:hover{color:#ed4259}.settings-wrapper .setting-list ul .font-size .resize .lang[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize .lang[data-v-65e7f0f4]{color:#a6a6a6;font-weight:400;font-family:FZZCYSK}.settings-wrapper .setting-list ul .font-size .resize b[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize b[data-v-65e7f0f4]{display:inline-block;height:20px;vertical-align:middle}.night[data-v-65e7f0f4] .selected,.night[data-v-65e7f0f4] .theme-item{border:1px solid #666}.night[data-v-65e7f0f4] .moon-icon{color:#ed4259}.night[data-v-65e7f0f4] .font-list .font-item,.night[data-v-65e7f0f4] .resize{border:1px solid #666;background:rgba(45,45,45,.5)}.night[data-v-65e7f0f4] .resize b{border-right:1px solid #666}.day[data-v-65e7f0f4] .theme-item{border:1px solid #e5e5e5}.day[data-v-65e7f0f4] .selected{border:1px solid #ed4259}.day[data-v-65e7f0f4] .moon-icon{display:inline;color:hsla(0,0%,100%,.2)}.day[data-v-65e7f0f4] .font-list .font-item{background:hsla(0,0%,100%,.5);border:1px solid rgba(0,0,0,.1)}.day[data-v-65e7f0f4] .resize{border:1px solid #e5e5e5;background:hsla(0,0%,100%,.5)}.day[data-v-65e7f0f4] .resize b{border-right:1px solid #e5e5e5}@media screen and (max-width:500px){.settings-wrapper i[data-v-65e7f0f4]{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-bottom:5px!important}}p[data-v-4684738b]{display:block;word-wrap:break-word;word-break:break-all}img[data-v-4684738b]{margin-left:auto;margin-right:auto;display:block;width:100%}[data-v-3a303318] .pop-setting{margin-left:68px;top:0}[data-v-3a303318] .pop-cata{margin-left:10px}[data-v-3a303318] .scroll-container{overflow-y:hidden!important}.chapter-wrapper[data-v-3a303318]{padding:0 4%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.chapter-wrapper[data-v-3a303318] .no-point{pointer-events:none}.chapter-wrapper .tool-bar[data-v-3a303318]{position:fixed;top:0;left:50%;z-index:100}.chapter-wrapper .tool-bar .tools[data-v-3a303318]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.chapter-wrapper .tool-bar .tools .tool-icon[data-v-3a303318]{font-size:18px;width:58px;height:48px;text-align:center;padding-top:12px;cursor:pointer;outline:none}.chapter-wrapper .tool-bar .tools .tool-icon .iconfont[data-v-3a303318]{font-family:iconfont;width:16px;height:16px;font-size:16px;margin:0 auto 6px}.chapter-wrapper .tool-bar .tools .tool-icon .icon-text[data-v-3a303318]{font-size:12px}.chapter-wrapper .read-bar[data-v-3a303318]{position:fixed;bottom:0;right:50%;z-index:100}.chapter-wrapper .read-bar .tools[data-v-3a303318]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.chapter-wrapper .read-bar .tools .tool-icon[data-v-3a303318]{font-size:18px;width:42px;height:31px;padding-top:12px;text-align:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;outline:none;margin-top:-1px}.chapter-wrapper .read-bar .tools .tool-icon .iconfont[data-v-3a303318]{font-family:iconfont;width:16px;height:16px;font-size:16px;margin:0 auto 6px}.chapter-wrapper .chapter-bar .el-breadcrumb .item[data-v-3a303318]{font-size:14px;color:#606266}.chapter-wrapper .chapter[data-v-3a303318]{font-family:Microsoft YaHei,PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,sans-serif;text-align:left;padding:0 65px;min-height:100vh;width:670px;margin:0 auto}.chapter-wrapper .chapter[data-v-3a303318] .el-icon-loading{font-size:36px;color:#b5b5b5}.chapter-wrapper .chapter[data-v-3a303318] .el-loading-text{font-weight:500;color:#b5b5b5}.chapter-wrapper .chapter .content[data-v-3a303318]{font-size:18px;line-height:1.8;overflow:hidden;font-family:Microsoft YaHei,PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,sans-serif}.chapter-wrapper .chapter .content .title[data-v-3a303318]{margin-bottom:57px;font:24px/32px PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,Microsoft YaHei,sans-serif}.chapter-wrapper .chapter .content .bottom-bar[data-v-3a303318],.chapter-wrapper .chapter .content .top-bar[data-v-3a303318]{height:64px}.day[data-v-3a303318] .popup{-webkit-box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04)}.day[data-v-3a303318] .tool-icon{border:1px solid rgba(0,0,0,.1);margin-top:-1px;color:#000}.day[data-v-3a303318] .tool-icon .icon-text{color:rgba(0,0,0,.4)}.day[data-v-3a303318] .chapter{border:1px solid #d8d8d8;color:#262626}.night[data-v-3a303318] .popup{-webkit-box-shadow:0 2px 4px rgba(0,0,0,.48),0 0 6px rgba(0,0,0,.16);box-shadow:0 2px 4px rgba(0,0,0,.48),0 0 6px rgba(0,0,0,.16)}.night[data-v-3a303318] .tool-icon{border:1px solid #444;margin-top:-1px;color:#666}.night[data-v-3a303318] .tool-icon .icon-text{color:#666}.night[data-v-3a303318] .chapter{border:1px solid #444;color:#666}.night[data-v-3a303318] .popper__arrow{background:#666}@media screen and (max-width:750px){.chapter-wrapper[data-v-3a303318]{padding:0}.chapter-wrapper .tool-bar[data-v-3a303318]{left:0;width:100vw;margin-left:0!important}.chapter-wrapper .tool-bar .tools[data-v-3a303318]{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.chapter-wrapper .tool-bar .tools .tool-icon[data-v-3a303318]{border:none}.chapter-wrapper .read-bar[data-v-3a303318]{right:0;width:100vw;margin-right:0!important}.chapter-wrapper .read-bar .tools[data-v-3a303318]{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:0 15px}.chapter-wrapper .read-bar .tools .tool-icon[data-v-3a303318]{border:none;width:auto}.chapter-wrapper .read-bar .tools .tool-icon .iconfont[data-v-3a303318]{display:inline-block}.chapter-wrapper .chapter[data-v-3a303318]{width:100vw!important;padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box}} \ No newline at end of file +@charset "UTF-8";@font-face{font-family:FZZCYSK;src:local("☺"),url(../fonts/popfont.f39ecc1a.ttf);font-style:normal;font-weight:400}.cata-wrapper[data-v-0aacaab8]{margin:-16px;padding:18px 0 24px 25px}.cata-wrapper .title[data-v-0aacaab8]{font-size:18px;font-weight:400;font-family:FZZCYSK;margin:0 0 20px 0;color:#ed4259;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;border-bottom:1px solid #ed4259}.cata-wrapper .data-wrapper[data-v-0aacaab8]{height:300px;overflow:auto}.cata-wrapper .data-wrapper .cata[data-v-0aacaab8]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.cata-wrapper .data-wrapper .cata .selected[data-v-0aacaab8]{color:#eb4259}.cata-wrapper .data-wrapper .cata .log[data-v-0aacaab8]{width:50%;height:40px;cursor:pointer;float:left;font:16px/40px PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,Microsoft YaHei,sans-serif}.cata-wrapper .data-wrapper .cata .log .log-text[data-v-0aacaab8]{margin-right:26px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.cata-wrapper .night[data-v-0aacaab8] .log{border-bottom:1px solid #666}.cata-wrapper .day[data-v-0aacaab8] .log{border-bottom:1px solid #f2f2f2}@media screen and (max-width:500px){.cata-wrapper .data-wrapper .cata .log[data-v-0aacaab8]{width:100%}}@font-face{font-family:iconfont;src:url(../fonts/iconfont.f9a3fb0e.woff) format("woff")}[data-v-65e7f0f4] .iconfont,[data-v-65e7f0f4] .moon-icon{font-family:iconfont;font-style:normal}.settings-wrapper[data-v-65e7f0f4]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;margin:-13px;height:300px;text-align:left;padding:40px 0 40px 24px;background:#ede7da url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyBAMAAADsEZWCAAAAD1BMVEX48dr48Nf58tv379X17NJtIBxUAAACFUlEQVQ4y1XRUZakMAgF0Af2AiDWApDZgHZqAV1nZv9rGh7Rj7Y8McUFEg1wvcMESMNVD/neU8Xcaz7nYYkYlYO6Ti82PBI4BvIEg1aj3wKwRvIMgZsUy5LdhCawPFh1sZs4SrlyN9fQKpv8s5dgZ2eLyqqJiu+WkCmUEybXkm3INS01WAiv0PapJ0CZc0SJQUzcWnZYbOOY20iFD8Bk+/j2A3wNxH7GdShFYS5ff237kXh9I9zSkQmIAhOsOSVfJ6DIXTMDaPnzkRJ92S1BQQmXl5LdirgRLLDdcYqcGPwe3QN4xCBiGNbrqq9wpW1XCecChwaQdVOsRDpPCpeoolPdxeXp3WNB9PHVzWBHlygy4NJCCrFHREv6bDt0VGwJZASkpONmm1UseGeFKAQexgaAkrfYWl3AGxWOLL2AIMBNbCXpktmS3k3vHeYjGCPBa43wJTurO3ZFVpQSJdAZGLoHTyk1upkjxMEaIxum3iIARcCa5kSkFAW5fi1mUlL9eyOsaanFmOMruwvEdE3ZYzsRSzo5ewRLXyVPPEvknt8ij4DvCg2O7xOgBCUprEzV4z1WekSpUgI8DT2mrnSOXKRfQavwuKA1F+tFnMKdJSUpMA7wQAifWRkMgjUKKZE4lBl6MCM4B1pq1P4uIjDE6Pq6rL0FnW1nIFmta5vrSvq/Ch4tpqG/ZNyyWa5jZPktq81eYv8Bt5s4iFITOp4AAAAASUVORK5CYII=) repeat}.settings-wrapper .settings-title[data-v-65e7f0f4]{font-size:18px;line-height:22px;margin-bottom:28px;font-family:FZZCYSK;font-weight:400}.settings-wrapper .setting-list ul[data-v-65e7f0f4]{list-style:none outside none;margin:0;padding:0}.settings-wrapper .setting-list ul li[data-v-65e7f0f4]{list-style:none outside none}.settings-wrapper .setting-list ul li i[data-v-65e7f0f4]{font:12px/16px PingFangSC-Regular,-apple-system,Simsun;display:inline-block;min-width:48px;margin-right:16px;vertical-align:middle;color:#666}.settings-wrapper .setting-list ul li .theme-item[data-v-65e7f0f4]{line-height:32px;width:34px;height:34px;margin-right:16px;margin-top:5px;border-radius:100%;display:inline-block;cursor:pointer;text-align:center;vertical-align:middle}.settings-wrapper .setting-list ul li .theme-item .iconfont[data-v-65e7f0f4]{display:none}.settings-wrapper .setting-list ul li .selected[data-v-65e7f0f4]{color:#ed4259}.settings-wrapper .setting-list ul li .selected .iconfont[data-v-65e7f0f4]{display:inline}.settings-wrapper .setting-list ul .font-list[data-v-65e7f0f4]{margin-top:28px}.settings-wrapper .setting-list ul .font-list .font-item[data-v-65e7f0f4]{width:78px;height:34px;cursor:pointer;margin-right:16px;border-radius:2px;text-align:center;vertical-align:middle;display:inline-block;font:14px/34px PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,Microsoft YaHei,sans-serif}.settings-wrapper .setting-list ul .font-list .font-item[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .font-list .selected[data-v-65e7f0f4]{color:#ed4259;border:1px solid #ed4259}.settings-wrapper .setting-list ul .font-size[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width[data-v-65e7f0f4]{margin-top:28px}.settings-wrapper .setting-list ul .font-size .resize[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize[data-v-65e7f0f4]{display:inline-block;width:274px;height:34px;vertical-align:middle;border-radius:2px}.settings-wrapper .setting-list ul .font-size .resize span[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize span[data-v-65e7f0f4]{width:89px;height:34px;line-height:34px;display:inline-block;cursor:pointer;text-align:center;vertical-align:middle}.settings-wrapper .setting-list ul .font-size .resize span em[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize span em[data-v-65e7f0f4]{font-style:normal}.settings-wrapper .setting-list ul .font-size .resize .less[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .font-size .resize .more[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .read-width .resize .less[data-v-65e7f0f4]:hover,.settings-wrapper .setting-list ul .read-width .resize .more[data-v-65e7f0f4]:hover{color:#ed4259}.settings-wrapper .setting-list ul .font-size .resize .lang[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize .lang[data-v-65e7f0f4]{color:#a6a6a6;font-weight:400;font-family:FZZCYSK}.settings-wrapper .setting-list ul .font-size .resize b[data-v-65e7f0f4],.settings-wrapper .setting-list ul .read-width .resize b[data-v-65e7f0f4]{display:inline-block;height:20px;vertical-align:middle}.night[data-v-65e7f0f4] .selected,.night[data-v-65e7f0f4] .theme-item{border:1px solid #666}.night[data-v-65e7f0f4] .moon-icon{color:#ed4259}.night[data-v-65e7f0f4] .font-list .font-item,.night[data-v-65e7f0f4] .resize{border:1px solid #666;background:rgba(45,45,45,.5)}.night[data-v-65e7f0f4] .resize b{border-right:1px solid #666}.day[data-v-65e7f0f4] .theme-item{border:1px solid #e5e5e5}.day[data-v-65e7f0f4] .selected{border:1px solid #ed4259}.day[data-v-65e7f0f4] .moon-icon{display:inline;color:hsla(0,0%,100%,.2)}.day[data-v-65e7f0f4] .font-list .font-item{background:hsla(0,0%,100%,.5);border:1px solid rgba(0,0,0,.1)}.day[data-v-65e7f0f4] .resize{border:1px solid #e5e5e5;background:hsla(0,0%,100%,.5)}.day[data-v-65e7f0f4] .resize b{border-right:1px solid #e5e5e5}@media screen and (max-width:500px){.settings-wrapper i[data-v-65e7f0f4]{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-bottom:5px!important}}p[data-v-4684738b]{display:block;word-wrap:break-word;word-break:break-all}img[data-v-4684738b]{margin-left:auto;margin-right:auto;display:block;width:100%}[data-v-6f059ee2] .pop-setting{margin-left:68px;top:0}[data-v-6f059ee2] .pop-cata{margin-left:10px}[data-v-6f059ee2] .scroll-container{overflow-y:hidden!important}.chapter-wrapper[data-v-6f059ee2]{padding:0 4%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.chapter-wrapper[data-v-6f059ee2] .no-point{pointer-events:none}.chapter-wrapper .tool-bar[data-v-6f059ee2]{position:fixed;top:0;left:50%;z-index:100}.chapter-wrapper .tool-bar .tools[data-v-6f059ee2]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.chapter-wrapper .tool-bar .tools .tool-icon[data-v-6f059ee2]{font-size:18px;width:58px;height:48px;text-align:center;padding-top:12px;cursor:pointer;outline:none}.chapter-wrapper .tool-bar .tools .tool-icon .iconfont[data-v-6f059ee2]{font-family:iconfont;width:16px;height:16px;font-size:16px;margin:0 auto 6px}.chapter-wrapper .tool-bar .tools .tool-icon .icon-text[data-v-6f059ee2]{font-size:12px}.chapter-wrapper .read-bar[data-v-6f059ee2]{position:fixed;bottom:0;right:50%;z-index:100}.chapter-wrapper .read-bar .tools[data-v-6f059ee2]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.chapter-wrapper .read-bar .tools .tool-icon[data-v-6f059ee2]{font-size:18px;width:42px;height:31px;padding-top:12px;text-align:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;outline:none;margin-top:-1px}.chapter-wrapper .read-bar .tools .tool-icon .iconfont[data-v-6f059ee2]{font-family:iconfont;width:16px;height:16px;font-size:16px;margin:0 auto 6px}.chapter-wrapper .chapter-bar .el-breadcrumb .item[data-v-6f059ee2]{font-size:14px;color:#606266}.chapter-wrapper .chapter[data-v-6f059ee2]{font-family:Microsoft YaHei,PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,sans-serif;text-align:left;padding:0 65px;min-height:100vh;width:670px;margin:0 auto}.chapter-wrapper .chapter[data-v-6f059ee2] .el-icon-loading{font-size:36px;color:#b5b5b5}.chapter-wrapper .chapter[data-v-6f059ee2] .el-loading-text{font-weight:500;color:#b5b5b5}.chapter-wrapper .chapter .content[data-v-6f059ee2]{font-size:18px;line-height:1.8;overflow:hidden;font-family:Microsoft YaHei,PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,sans-serif}.chapter-wrapper .chapter .content .title[data-v-6f059ee2]{margin-bottom:57px;font:24px/32px PingFangSC-Regular,HelveticaNeue-Light,Helvetica Neue Light,Microsoft YaHei,sans-serif}.chapter-wrapper .chapter .content .bottom-bar[data-v-6f059ee2],.chapter-wrapper .chapter .content .top-bar[data-v-6f059ee2]{height:64px}.day[data-v-6f059ee2] .popup{-webkit-box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04)}.day[data-v-6f059ee2] .tool-icon{border:1px solid rgba(0,0,0,.1);margin-top:-1px;color:#000}.day[data-v-6f059ee2] .tool-icon .icon-text{color:rgba(0,0,0,.4)}.day[data-v-6f059ee2] .chapter{border:1px solid #d8d8d8;color:#262626}.night[data-v-6f059ee2] .popup{-webkit-box-shadow:0 2px 4px rgba(0,0,0,.48),0 0 6px rgba(0,0,0,.16);box-shadow:0 2px 4px rgba(0,0,0,.48),0 0 6px rgba(0,0,0,.16)}.night[data-v-6f059ee2] .tool-icon{border:1px solid #444;margin-top:-1px;color:#666}.night[data-v-6f059ee2] .tool-icon .icon-text{color:#666}.night[data-v-6f059ee2] .chapter{border:1px solid #444;color:#666}.night[data-v-6f059ee2] .popper__arrow{background:#666}@media screen and (max-width:750px){.chapter-wrapper[data-v-6f059ee2]{padding:0}.chapter-wrapper .tool-bar[data-v-6f059ee2]{left:0;width:100vw;margin-left:0!important}.chapter-wrapper .tool-bar .tools[data-v-6f059ee2]{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.chapter-wrapper .tool-bar .tools .tool-icon[data-v-6f059ee2]{border:none}.chapter-wrapper .read-bar[data-v-6f059ee2]{right:0;width:100vw;margin-right:0!important}.chapter-wrapper .read-bar .tools[data-v-6f059ee2]{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:0 15px}.chapter-wrapper .read-bar .tools .tool-icon[data-v-6f059ee2]{border:none;width:auto}.chapter-wrapper .read-bar .tools .tool-icon .iconfont[data-v-6f059ee2]{display:inline-block}.chapter-wrapper .chapter[data-v-6f059ee2]{width:100vw!important;padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box}} \ No newline at end of file diff --git a/app/src/main/assets/web/bookshelf/index.html b/app/src/main/assets/web/bookshelf/index.html index 021b42c1d..60fd1fe3e 100644 --- a/app/src/main/assets/web/bookshelf/index.html +++ b/app/src/main/assets/web/bookshelf/index.html @@ -1,3 +1,3 @@ -Legado Bookshelf
\ No newline at end of file + }
\ No newline at end of file diff --git a/app/src/main/assets/web/bookshelf/js/about.56b5bbf2.js b/app/src/main/assets/web/bookshelf/js/about.a288ed22.js similarity index 100% rename from app/src/main/assets/web/bookshelf/js/about.56b5bbf2.js rename to app/src/main/assets/web/bookshelf/js/about.a288ed22.js diff --git a/app/src/main/assets/web/bookshelf/js/app.f9143363.js b/app/src/main/assets/web/bookshelf/js/app.cfea0936.js similarity index 74% rename from app/src/main/assets/web/bookshelf/js/app.f9143363.js rename to app/src/main/assets/web/bookshelf/js/app.cfea0936.js index 4173348ed..959ff715c 100644 --- a/app/src/main/assets/web/bookshelf/js/app.f9143363.js +++ b/app/src/main/assets/web/bookshelf/js/app.cfea0936.js @@ -1 +1 @@ -(function(e){function t(t){for(var r,o,u=t[0],c=t[1],f=t[2],s=0,l=[];s>>32-t}function r(e,t){var n,r,o,a,i;return o=2147483648&e,a=2147483648&t,n=1073741824&e,r=1073741824&t,i=(1073741823&e)+(1073741823&t),n&r?2147483648^i^o^a:n|r?1073741824&i?3221225472^i^o^a:1073741824^i^o^a:i^o^a}function o(e,t,n){return e&t|~e&n}function a(e,t,n){return e&n|t&~n}function i(e,t,n){return e^t^n}function u(e,t,n){return t^(e|~n)}function c(e,t,a,i,u,c,f){return e=r(e,r(r(o(t,a,i),u),f)),r(n(e,c),t)}function f(e,t,o,i,u,c,f){return e=r(e,r(r(a(t,o,i),u),f)),r(n(e,c),t)}function s(e,t,o,a,u,c,f){return e=r(e,r(r(i(t,o,a),u),f)),r(n(e,c),t)}function l(e,t,o,a,i,c,f){return e=r(e,r(r(u(t,o,a),i),f)),r(n(e,c),t)}function d(e){var t,n=e.length,r=n+8,o=(r-r%64)/64,a=16*(o+1),i=Array(a-1),u=0,c=0;while(c>>29,i}function p(e){var t,n,r="",o="";for(n=0;n<=3;n++)t=e>>>8*n&255,o="0"+t.toString(16),r+=o.substr(o.length-2,2);return r}var b,h,g,m,v,y,w,C,S,O=Array(),j=7,k=12,x=17,P=22,T=5,_=9,E=14,L=20,$=4,A=11,M=16,B=23,N=6,I=10,V=15,R=21;for(O=d(t),y=1732584193,w=4023233417,C=2562383102,S=271733878,b=0;b>>32-t}function r(e,t){var n,r,o,a,i;return o=2147483648&e,a=2147483648&t,n=1073741824&e,r=1073741824&t,i=(1073741823&e)+(1073741823&t),n&r?2147483648^i^o^a:n|r?1073741824&i?3221225472^i^o^a:1073741824^i^o^a:i^o^a}function o(e,t,n){return e&t|~e&n}function a(e,t,n){return e&n|t&~n}function i(e,t,n){return e^t^n}function u(e,t,n){return t^(e|~n)}function c(e,t,a,i,u,c,f){return e=r(e,r(r(o(t,a,i),u),f)),r(n(e,c),t)}function f(e,t,o,i,u,c,f){return e=r(e,r(r(a(t,o,i),u),f)),r(n(e,c),t)}function s(e,t,o,a,u,c,f){return e=r(e,r(r(i(t,o,a),u),f)),r(n(e,c),t)}function l(e,t,o,a,i,c,f){return e=r(e,r(r(u(t,o,a),i),f)),r(n(e,c),t)}function d(e){var t,n=e.length,r=n+8,o=(r-r%64)/64,a=16*(o+1),i=Array(a-1),u=0,c=0;while(c>>29,i}function p(e){var t,n,r="",o="";for(n=0;n<=3;n++)t=e>>>8*n&255,o="0"+t.toString(16),r+=o.substr(o.length-2,2);return r}var h,b,g,m,v,y,w,C,S,O=Array(),j=7,k=12,x=17,P=22,T=5,_=9,E=14,L=20,$=4,A=11,M=16,B=23,N=6,I=10,V=15,R=21;for(O=d(t),y=1732584193,w=4023233417,C=2562383102,S=271733878,h=0;hb)","g");return"b"!==t.exec("b").groups.a||"bc"!=="b".replace(t,"$c")}))},1276:function(t,e,n){"use strict";var o=n("2ba4"),i=n("c65b"),r=n("e330"),s=n("d784"),a=n("44e7"),c=n("825a"),l=n("1d80"),u=n("4840"),f=n("8aa5"),d=n("50c4"),h=n("577e"),p=n("dc4a"),g=n("4dae"),A=n("14c3"),m=n("9263"),v=n("9f7f"),b=n("d039"),y=v.UNSUPPORTED_Y,C=4294967295,x=Math.min,S=[].push,B=r(/./.exec),w=r(S),I=r("".slice),E=!b((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));s("split",(function(t,e,n){var r;return r="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,n){var r=h(l(this)),s=void 0===n?C:n>>>0;if(0===s)return[];if(void 0===t)return[r];if(!a(t))return i(e,r,t,s);var c,u,f,d=[],p=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),A=0,v=new RegExp(t.source,p+"g");while(c=i(m,v,r)){if(u=v.lastIndex,u>A&&(w(d,I(r,A,c.index)),c.length>1&&c.index=s))break;v.lastIndex===c.index&&v.lastIndex++}return A===r.length?!f&&B(v,"")||w(d,""):w(d,I(r,A)),d.length>s?g(d,0,s):d}:"0".split(void 0,0).length?function(t,n){return void 0===t&&0===n?[]:i(e,this,t,n)}:e,[function(e,n){var o=l(this),s=void 0==e?void 0:p(e,t);return s?i(s,e,o,n):i(r,h(o),e,n)},function(t,o){var i=c(this),s=h(t),a=n(r,i,s,o,r!==e);if(a.done)return a.value;var l=u(i,RegExp),p=i.unicode,g=(i.ignoreCase?"i":"")+(i.multiline?"m":"")+(i.unicode?"u":"")+(y?"g":"y"),m=new l(y?"^(?:"+i.source+")":i,g),v=void 0===o?C:o>>>0;if(0===v)return[];if(0===s.length)return null===A(m,s)?[s]:[];var b=0,S=0,B=[];while(S1&&void 0!==arguments[1]?arguments[1]:{};switch(l=d.duration||1e3,i=d.offset||0,p=d.callback,r=d.easing||u,s=d.a11y||!1,a(d.container)){case"object":t=d.container;break;case"string":t=document.querySelector(d.container);break;default:t=window}switch(n=g(),a(f)){case"number":e=void 0,s=!1,o=n+f;break;case"object":e=f,o=A(e);break;case"string":e=document.querySelector(f),o=A(e);break}switch(c=o-n+i,a(d.duration)){case"number":l=d.duration;break;case"function":l=d.duration(c);break}requestAnimationFrame(v)}return y},d=f(),h=d,p=n("7286"),g=n.n(p),A=n("477e"),m=n.n(A),v=n("e160"),b=n.n(v),y=n("df5e"),C=n.n(y),x=n("ec0f"),S=n.n(x),B=n("b671"),w=n.n(B),I=n("5629"),E=n.n(I),k=n("d0e3"),T=n.n(k),D=n("4039"),U=n.n(D),P=n("1e75"),O=n.n(P),R=n("1632"),Q=n.n(R),V=n("7abd"),M=n.n(V),N=n("356c"),F=n.n(N),L=n("b165"),K=n.n(L),H=n("cf68"),W=n.n(H),J=n("4400"),z=n.n(J),Y=n("802e"),j=n.n(Y),G=n("0827"),q=n.n(G),Z={themes:[{body:"#ede7da url("+g.a+") repeat",content:"#ede7da url("+m.a+") repeat",popup:"#ede7da url("+b.a+") repeat"},{body:"#ede7da url("+C.a+") repeat",content:"#ede7da url("+S.a+") repeat",popup:"#ede7da url("+w.a+") repeat"},{body:"#ede7da url("+E.a+") repeat",content:"#ede7da url("+T.a+") repeat",popup:"#ede7da url("+U.a+") repeat"},{body:"#ede7da url("+O.a+") repeat",content:"#ede7da url("+Q.a+") repeat",popup:"#ede7da url("+M.a+") repeat"},{body:"#ebcece repeat",content:"#f5e4e4 repeat",popup:"#faeceb repeat"},{body:"#ede7da url("+F.a+") repeat",content:"#ede7da url("+K.a+") repeat",popup:"#ede7da url("+W.a+") repeat"},{body:"#ede7da url("+z.a+") repeat",content:"#ede7da url("+j.a+") repeat",popup:"#ede7da url("+q.a+") repeat"}],fonts:[{fontFamily:"Microsoft YaHei, PingFangSC-Regular, HelveticaNeue-Light, Helvetica Neue Light, sans-serif"},{fontFamily:"PingFangSC-Regular, -apple-system, Simsun"},{fontFamily:"Kaiti"}]},X=Z,$=(n("05b3"),{name:"PopCata",data:function(){return{isNight:6==this.$store.state.config.theme,index:this.$store.state.readingBook.index}},computed:{catalog:function(){return this.$store.state.readingBook.catalog},popCataVisible:function(){return this.$store.state.popCataVisible},theme:function(){return this.$store.state.config.theme},popupTheme:function(){return{background:X.themes[this.theme].popup}}},mounted:function(){},watch:{theme:function(t){this.isNight=6==t},popCataVisible:function(){this.$nextTick((function(){var t=this.$store.state.readingBook.index,e=this.$refs.cataData;h(this.$refs.cata[t],{container:e,duration:0})}))}},methods:{isSelected:function(t){return t==this.$store.state.readingBook.index},gotoChapter:function(t){this.index=this.catalog.indexOf(t),this.$store.commit("setPopCataVisible",!1),this.$store.commit("setContentLoading",!0),this.$emit("getContent",this.index)}}}),_=$,tt=(n("635f"),n("2877")),et=Object(tt["a"])(_,r,s,!1,null,"0aacaab8",null),nt=et.exports,ot=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"settings-wrapper",class:{night:t.isNight,day:!t.isNight},style:t.popupTheme},[n("div",{staticClass:"settings-title"},[t._v("设置")]),n("div",{staticClass:"setting-list"},[n("ul",[n("li",{staticClass:"theme-list"},[n("i",[t._v("阅读主题")]),t._l(t.themeColors,(function(e,o){return n("span",{key:o,ref:"themes",refInFor:!0,staticClass:"theme-item",class:{selected:t.selectedTheme==o},style:e,on:{click:function(e){return t.setTheme(o)}}},[o<6?n("em",{staticClass:"iconfont"},[t._v("")]):n("em",{staticClass:"moon-icon"},[t._v(t._s(t.moonIcon))])])}))],2),n("li",{staticClass:"font-list"},[n("i",[t._v("正文字体")]),t._l(t.fonts,(function(e,o){return n("span",{key:o,staticClass:"font-item",class:{selected:t.selectedFont==o},on:{click:function(e){return t.setFont(o)}}},[t._v(t._s(e))])}))],2),n("li",{staticClass:"font-size"},[n("i",[t._v("字体大小")]),n("div",{staticClass:"resize"},[n("span",{staticClass:"less",on:{click:t.lessFontSize}},[n("em",{staticClass:"iconfont"},[t._v("")])]),n("b"),t._v(" "),n("span",{staticClass:"lang"},[t._v(t._s(t.fontSize))]),n("b"),n("span",{staticClass:"more",on:{click:t.moreFontSize}},[n("em",{staticClass:"iconfont"},[t._v("")])])])]),t.$store.state.miniInterface?t._e():n("li",{staticClass:"read-width"},[n("i",[t._v("页面宽度")]),n("div",{staticClass:"resize"},[n("span",{staticClass:"less",on:{click:t.lessReadWidth}},[n("em",{staticClass:"iconfont"},[t._v("")])]),n("b"),t._v(" "),n("span",{staticClass:"lang"},[t._v(t._s(t.readWidth))]),n("b"),n("span",{staticClass:"more",on:{click:t.moreReadWidth}},[n("em",{staticClass:"iconfont"},[t._v("")])])])])])])])},it=[],rt=(n("82da"),n("b3f5")),st={name:"ReadSettings",data:function(){return{theme:0,isNight:6==this.$store.state.config.theme,moonIcon:"",themeColors:[{background:"rgba(250, 245, 235, 0.8)"},{background:"rgba(245, 234, 204, 0.8)"},{background:"rgba(230, 242, 230, 0.8)"},{background:"rgba(228, 241, 245, 0.8)"},{background:"rgba(245, 228, 228, 0.8)"},{background:"rgba(224, 224, 224, 0.8)"},{background:"rgba(0, 0, 0, 0.5)"}],moonIconStyle:{display:"inline",color:"rgba(255,255,255,0.2)"},fonts:["雅黑","宋体","楷书"]}},mounted:function(){var t=this.$store.state.config;this.theme=t.theme,6==this.theme?this.moonIcon="":this.moonIcon=""},computed:{config:function(){return this.$store.state.config},popupTheme:function(){return{background:X.themes[this.config.theme].popup}},selectedTheme:function(){return this.$store.state.config.theme},selectedFont:function(){return this.$store.state.config.font},fontSize:function(){return this.$store.state.config.fontSize},readWidth:function(){return this.$store.state.config.readWidth}},methods:{setTheme:function(t){6==t?(this.isNight=!0,this.moonIcon="",this.moonIconStyle.color="#ed4259"):(this.isNight=!1,this.moonIcon="",this.moonIconStyle.color="rgba(255,255,255,0.2)");var e=this.config;e.theme=t,this.$store.commit("setConfig",e),this.uploadConfig()},setFont:function(t){var e=this.config;e.font=t,this.$store.commit("setConfig",e),this.uploadConfig()},moreFontSize:function(){var t=this.config;t.fontSize<48&&(t.fontSize+=2),this.$store.commit("setConfig",t),this.uploadConfig()},lessFontSize:function(){var t=this.config;t.fontSize>12&&(t.fontSize-=2),this.$store.commit("setConfig",t),this.uploadConfig()},moreReadWidth:function(){var t=this.config;t.readWidth<960&&(t.readWidth+=160),this.$store.commit("setConfig",t),this.uploadConfig()},lessReadWidth:function(){var t=this.config;t.readWidth>640&&(t.readWidth-=160),this.$store.commit("setConfig",t),this.uploadConfig()},uploadConfig:function(){rt["a"].post("/saveReadConfig",this.config)}}},at=st,ct=(n("0928"),Object(tt["a"])(at,ot,it,!1,null,"65e7f0f4",null)),lt=ct.exports,ut=(n("d81d"),n("00b4"),n("466d"),{name:"pcontent",data:function(){return{}},props:["carray"],render:function(){var t=this,e=arguments[0],n=this.fontFamily,o=this.fontSize,i=n;return i.fontSize=o,this.show?e("div",[this.carray.map((function(n){return/]*src/.test(n)?e("img",{directives:[{name:"lazy",value:t.proxyImage(n)}]}):e("p",{style:i,domProps:{innerHTML:n}})}))]):e("div")},computed:{show:function(){return this.$store.state.showContent},fontFamily:function(){return X.fonts[this.$store.state.config.font]},fontSize:function(){return this.$store.state.config.fontSize+"px"}},methods:{proxyImage:function(t){var e=/]*src="([^"]*(?:"[^>]+\})?)"[^>]*>/,n=t.match(e)[1];return/^data:/.test(n)?n:"../../image?path="+encodeURIComponent(n)+"&url="+encodeURIComponent(sessionStorage.getItem("bookUrl"))+"&width="+this.$store.state.config.readWidth}},watch:{fontSize:function(){var t=this;t.$store.commit("setShowContent",!1),this.$nextTick((function(){t.$store.commit("setShowContent",!0)}))}}}),ft=ut,dt=(n("e3cf"),Object(tt["a"])(ft,c,l,!1,null,"4684738b",null)),ht=dt.exports,pt=n("897d"),gt=n.n(pt),At={components:{PopCata:nt,Pcontent:ht,ReadSettings:lt,PullTo:gt.a},created:function(){var t=JSON.parse(localStorage.getItem("config"));null!=t&&this.$store.commit("setConfig",t)},beforeCreate:function(){var t=JSON.parse(localStorage.getItem("config"));null!=t&&this.$store.commit("setConfig",t)},mounted:function(){var t=this;this.loading=this.$loading({target:this.$refs.content,lock:!0,text:"正在获取内容",spinner:"el-icon-loading",background:"rgba(0,0,0,0)"});var e=this,n=sessionStorage.getItem("bookUrl"),o=sessionStorage.getItem("bookName"),i=sessionStorage.getItem("chapterIndex")||0,r=JSON.parse(localStorage.getItem(n));(null==r||i>0)&&(r={bookName:o,bookUrl:n,index:i},localStorage.setItem(n,JSON.stringify(r))),this.getCatalog(n).then((function(n){var o=n.data.data;r.catalog=o,e.$store.commit("setReadingBook",r);var i=e.$store.state.readingBook.index||0;t.getContent(i),window.addEventListener("keyup",t.handleKeyPress),window.addEventListener("scroll",t.handleScroll)}),(function(t){throw e.loading.close(),e.$message.error("获取书籍目录失败"),t}))},destroyed:function(){window.removeEventListener("keyup",this.handleKeyPress),window.removeEventListener("scroll",this.handleScroll),this.readSettingsVisible=!1,this.popCataVisible=!1},watch:{title:function(){document.title=sessionStorage.getItem("bookName")+" | "+this.title},content:function(){var t=this;this.$store.commit("setContentLoading",!1),setTimeout((function(){return t.handleScroll()}),500)},theme:function(t){this.isNight=6==t},bodyColor:function(t){this.bodyTheme.background=t},chapterColor:function(t){this.chapterTheme.background=t},readWidth:function(t){this.chapterTheme.width=t;var e=-((parseInt(t)+130)/2+68)+"px",n=-((parseInt(t)+130)/2+52)+"px";this.leftBarTheme.marginLeft=e,this.rightBarTheme.marginRight=n},popupColor:function(t){this.leftBarTheme.background=t,this.rightBarTheme.background=t},readSettingsVisible:function(t){if(!t){var e=JSON.stringify(this.$store.state.config);localStorage.setItem("config",e)}}},data:function(){return{title:"",content:[],noPoint:!0,showToolBar:!1,onTop:!0,onBottom:!1,topConfig:{pullText:"加载上一章",triggerText:"松开加载上一章"},bottomConfig:{pullText:"加载下一章",triggerText:"松开加载下一章"}}},computed:{catalog:function(){return this.$store.state.catalog},windowHeight:function(){return window.innerHeight},contentHeight:function(){return this.$refs.content.offsetHeight},popCataVisible:{get:function(){return this.$store.state.popCataVisible},set:function(t){this.$store.commit("setPopCataVisible",t)}},readSettingsVisible:{get:function(){return this.$store.state.readSettingsVisible},set:function(t){this.$store.commit("setReadSettingsVisible",t)}},config:function(){return this.$store.state.config},theme:function(){return this.config.theme},bodyColor:function(){return X.themes[this.config.theme].body},chapterColor:function(){return X.themes[this.config.theme].content},popupColor:function(){return X.themes[this.config.theme].popup},isNight:function(){return 6==this.$store.state.config.theme},readWidth:function(){return this.$store.state.miniInterface?window.innerWidth+"px":this.$store.state.config.readWidth-130+"px"},popupWidth:function(){return this.$store.state.miniInterface?window.innerWidth-33:this.$store.state.config.readWidth-33},bodyTheme:function(){return{background:X.themes[this.$store.state.config.theme].body}},chapterTheme:function(){return{background:X.themes[this.$store.state.config.theme].content,width:this.readWidth}},leftBarTheme:function(){return{background:X.themes[this.$store.state.config.theme].popup,marginLeft:this.$store.state.miniInterface?0:-(this.$store.state.config.readWidth/2+68)+"px",display:this.$store.state.miniInterface&&!this.showToolBar?"none":"block"}},rightBarTheme:function(){return{background:X.themes[this.$store.state.config.theme].popup,marginRight:this.$store.state.miniInterface?0:-(this.$store.state.config.readWidth/2+52)+"px",display:this.$store.state.miniInterface&&!this.showToolBar?"none":"block"}},show:function(){return this.$store.state.showContent}},methods:{getCatalog:function(t){return rt["a"].get("/getChapterList?url="+encodeURIComponent(t))},getContent:function(t){var e=this;this.$store.commit("setShowContent",!1),this.loading.visible||(this.loading=this.$loading({target:this.$refs.content,lock:!0,text:"正在获取内容",spinner:"el-icon-loading",background:"rgba(0,0,0,0)"}));var n=sessionStorage.getItem("bookUrl"),o=JSON.parse(localStorage.getItem(n));o.index=t,localStorage.setItem(n,JSON.stringify(o)),this.$store.state.readingBook.index=t,sessionStorage.setItem("chapterIndex",t);var i=this.$store.state.readingBook.catalog[t].title,r=this.$store.state.readingBook.catalog[t].index;this.title=i,h(this.$refs.top,{duration:0});var s=this;rt["a"].get("/getBookContent?url="+encodeURIComponent(n)+"&index="+r).then((function(t){if(t.data.isSuccess){var n=t.data.data;s.content=n.split(/\n+/)}else s.$message.error("书源正文解析错误!"),s.content=["书源正文解析失败!"];if(e.$store.commit("setContentLoading",!0),s.loading.close(),s.noPoint=!1,s.$store.commit("setShowContent",!0),!t.data.isSuccess)throw t.data}),(function(t){throw s.$message.error("获取章节内容失败"),s.content=["获取章节内容失败!"],s.loading.close(),s.$store.commit("setShowContent",!0),t}))},toTop:function(){h(this.$refs.top)},toBottom:function(){h(this.$refs.bottom)},toNextChapter:function(t){this.$store.commit("setContentLoading",!0);var e=this.$store.state.readingBook.index;e++,"function"===typeof t&&t("done"),"undefined"!==typeof this.$store.state.readingBook.catalog[e]?(this.$message.info("下一章"),this.getContent(e)):this.$message.error("本章是最后一章")},toLastChapter:function(t){this.$store.commit("setContentLoading",!0);var e=this.$store.state.readingBook.index;e--,"function"===typeof t&&t("done"),"undefined"!==typeof this.$store.state.readingBook.catalog[e]?(this.$message.info("上一章"),this.getContent(e)):this.$message.error("本章是第一章")},toShelf:function(){this.$router.push("/")},handleKeyPress:function(t){switch(t.key){case"ArrowLeft":t.stopPropagation(),t.preventDefault(),this.toLastChapter();break;case"ArrowRight":t.stopPropagation(),t.preventDefault(),this.toNextChapter();break;case"ArrowUp":t.stopPropagation(),t.preventDefault(),0===document.documentElement.scrollTop?this.$message.warning("已到达页面顶部"):h(0-document.documentElement.clientHeight+100);break;case"ArrowDown":t.stopPropagation(),t.preventDefault(),document.documentElement.clientHeight+document.documentElement.scrollTop===document.documentElement.scrollHeight?this.$message.warning("已到达页面底部"):h(document.documentElement.clientHeight-100);break}},handleScroll:function(){var t=document.documentElement;this.onTop=0===t.scrollTop,this.onBottom=t.scrollTop+t.clientHeight>=t.scrollHeight}}},mt=At,vt=(n("be50"),Object(tt["a"])(mt,o,i,!1,null,"6f059ee2",null));e["default"]=vt.exports},5629:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXN383Q4tDP4c/R5NEInCCXAAACVElEQVQozw3Hv2sTYRwH4M/79pJ7bZL2bXqtERJ97zjUpbZDhg6pfC8qibi8hLR0EaJ0EFxaCSWDxjfpj1zrYBcRBKE6SAfBJWsx9i8IQfdQxDlKtA6t2OnhQfN3lbG7ytYRywF8rVoPCNO0X2sQOKDpAnSDK2VwkHgmh5yLGT8qASt+2KofnNt2Xg1gf1UF8AoM6052cRMNaloLZb7RKQGrKKji2OefsZF+VqIvos5ZLVIZCX61JcwUdk56wASVkgQvzPfvmT2twTSwyYaC/Pl/UhAHorFhBgZtL6XdAZRp1tkPwC1NLa9CWs5prLhI85NBQsLdXvjDymG3/EbYfQhVNYqc3TtktQhWLY3ko0QsdMbSEp+64v0NfxyqLbIGdh6M2xHHlLBGqKTyQo4E/nebBgBfe1GpdeywYXc8CT7D3cKXuMXkBy4xN6o5OuKamYp3DVI6uccO9lxgd2CAlJgI2BGgaAgIJV/TYwKqu3WFccjbMuA+bVkWgS2bfnlRbD1Eb1sDyWMmjKYIBgGAWbqKRicfvzBkBIz3V5AKnguWdglQEysQsSuVzOg6ALy1pitA5ykGCsc857BRYcgCSZyFOdvoOigSGoPc5Ta73mgxshIcQE5sHMHd9D7yqITw7JO+GHVMxjhzYLcKPSEgmz3fU+BRy3iYNtiXLaBssCW8KguReqkQOTb3MStV0Ugt4U1eIs1RZWRII6Ww8xeNNItyGGQI4ZMlpg/3lQtkl2JFnBp1imRyFe0kK2Id3PCslMgiQNMS77gvFeDhG3cSkYvheeg/e7ClIh5oh+IAAAAASUVORK5CYII="},"635f":function(t,e,n){"use strict";n("6c5b")},"6c5b":function(t,e,n){},7286:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXr5djn4dTp49bt59rT6LKxAAACnElEQVQozw3NUUwScRzA8d8R6MF8YMIx8uk47hDSJbj14IPzOGc7jPLvwTGg5uAYDbe2tt56cLtznvEnS6yDqCcEaWi91DvrbLJZz7b1aFtz1aO+2OZWvn+/+4CHeB6BMYaqBLfjPNRY6RFT2JJYby+uAk4WUTrtlmJ4hgPYb2q1XGDQjaK8pgJHvqNaAX+KyuIkDXpgQinb46nOulnn4b5laUHTxLfseeArAoNOeJlOIjdoal0n1FA7tKFv5roK+YaHOqP3P0XyKHPHY+MhTRe5uCZnKhtJKw2eSrSoBDPLtpZuNcFNJcFyiCMxOaaHIfXz1e8HQbWLySrBQ4x0x1qlhnHlnz2HQEC6TNb0gTHXa7IKhcaHqkE015hk9whA0YeWiLIXf7Fa2CZo3DjqjB4tTuF8jIcbfcEx5z/w4sXpQhXW+ju0cqh7icTFmRMaG+v6CIvTjcSpHcH8JEsF3EPh3fRthYdVLLgI2fWXm85/pGFE4l046s70L+yKCcirGFR+jbpy3kMmiCGHrSezVONsn1RBixncyk2PcVWk7DlgxHo8iZwDyq5uAUD854dZhdIFYzKoQig2haUKi1lVufz2RZUZPZ41n/hrOQB6h0Hhg8I367FNoEHgeM/KY7szSeQwD8q2WE3HM35ZLl0K1MJiOtHIkBclRQUwZnyOWcNsRQQgVLj1PSqkjF9DsoOSaSg3iinKzvfmgsNFFfpP/2T3GLGvL4fHEfwIX1sVvXcPqLztehWGcfn9nI2U9nTfCgJPe/jFPLZwgVEzimBgAm0VIyK2tt1cE/AzQdLK+SxLSQ4aDCZnnId94OG2S1XwvnTbNk/ZnhyRCQT+sZM6z9g6LXL1BOBe+zJySiFkHAINCtnQokbCJ/apCv0foqPiZVfhpywAAAAASUVORK5CYII="},7450:function(t,e,n){},"746f":function(t,e,n){var o=n("428f"),i=n("1a2d"),r=n("e538"),s=n("9bf2").f;t.exports=function(t){var e=o.Symbol||(o.Symbol={});i(e,t)||s(e,t,{value:r.f(t)})}},7715:function(t,e,n){},"7abd":function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXm9PXq+Pno9vfs+vttWKBGAAACPElEQVQozw3RQWrbQACF4TfCMjPqZgIj4RRaxsZKE0PuMBZ2cLKaCI9RDAXFmJJknUWWI1O1UlamOMHJSjGkuFn3AD2Cr9CepDrAg+/xIxK4QwIqHHQkUhQ/WuphInVIFBojl8QXc012Tgq4RTtVHWVLZVFh1tEoI91uiN4joCqde8Ukn/zGM1B2W4ari2PtTwyw55Ld+Wways54qhGPyS6FzbIT3lIY8WwWdCq56Yolx6KmSKzoqrsCB5heAp4TGNQWJ1Pc6XlE5jQD5OlIX9I47A9uiUQcPQxcury/ToyxWJG/za6ki88crxKPocKS59Sl3EtBG7C89fCGflpfqoSzCeC4crioJA7F0V5+8MaSIk4qSCdwzpogmbqzEirVpGiS2dOVJvUuuqFEmhHao06KEpq+8lvHI14NJk3Qrmi9vBuRLwAz0qZB4hsDXQFXgtnlpDX3C6ug9BquSw/CYtwAzuTz5vuQNdr/YibhR68378ehZH30FSpjh71LpQkrsj+Q062h5WwZ5wlRoD6uQJy1DqvSYuCUapMBqT5YA4ZFw4KlWapxoUGlKWrx0eDQvmigu4WMYt97ruru98fYL8/0lG6CTOFcFWBhFK5gKw19h2JN808nh7xhkU6sWKLXdtkqBL6h+lULK5k19wFB/FldnGYf3LDeuf6IC2/MzJOSOP0qPxLqzaGIqtBcFIItrstkazONOkrc1D1czjuwEGESB4JJnjgSMN7PXAu7fZQpl1C236C+9mM4Af8P98Ch4R2TRl8AAAAASUVORK5CYII="},"802e":function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEUWGBkYGhsdHyAfISI1t/v6AAAB5ElEQVQozxXQsYoTURSA4f/EeycZsDgDdySDjihk38Hy3GWi2J2BCaziQhaiaB+tt9AFu1kwvYUPsIXNPoB9BAUfwAfwEUzKv/v4odGrroyp9/rUaC6rZ5skv5F8qPsfYYP+yKUMymmAEEeW55oUR4o8jr05KNzJ07yvB7w0KKfLwcQUSjfmMU0PJfPHFoEVU+ohNrcKMEzMQ23FDnVSI2dqtYWI7KlLu6vE4UnyvKc3SJuL7lBbeEEl42ItpGLjzIT8PRJCmkRjVpVpsbJFVN0687okJNZiHAr5Z7MV0BnGIDc+THM1zlbieBc1Fq+tH5BH+OpnbWkj40hSqC8Lw2TvFuF0SUFJCk2IytXbjeqcRAt6NHpnrUkUU4KRzZs8RCK8N/Akn2W04LwxMU/V7XK0bDyN2RxfDyx7I4h5vjZby72V8UnOWumZL3qtYc+8DTE0siSBMXGhywx2dMYPnQHbxdFZ7deiNGxCCtD/QWnbwDoGhRYPDzUdUA3krjpnkvdAgDN4ddLkEQSov9qjd42HaDjI34gEqS9TUueAk+sc4qg5ws407KQYKs8G1jv4xBlqBVk6cb4dISZIwVi1Jzu4+HLk6lyfUxkXvwy+1Q+4WVdHIhwfybZ6CWVhxMEhShOgsP/HOW0MvZJeFwAAAABJRU5ErkJggg=="},"82da":function(t,e,n){},"897d":function(t,e,n){(function(e,n){t.exports=n()})(window,(function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var i=e[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=9)}([function(t,e,n){var o=n(7);"string"===typeof o&&(o=[[t.i,o,""]]),o.locals&&(t.exports=o.locals);var i=n(10).default;i("56ca1821",o,!1,{})},function(t,e,n){var o=n(3),i=n(4),r=n(5);function s(t,e){return o(t)||i(t,e)||r()}t.exports=s},function(t,e){function n(t){return n="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function o(e){return"function"===typeof Symbol&&"symbol"===n(Symbol.iterator)?t.exports=o=function(t){return n(t)}:t.exports=o=function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":n(t)},o(e)}t.exports=o},function(t,e){function n(t){if(Array.isArray(t))return t}t.exports=n},function(t,e){function n(t,e){var n=[],o=!0,i=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(o=(s=a.next()).done);o=!0)if(n.push(s.value),e&&n.length===e)break}catch(c){i=!0,r=c}finally{try{o||null==a["return"]||a["return"]()}finally{if(i)throw r}}return n}t.exports=n},function(t,e){function n(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}t.exports=n},function(t,e,n){"use strict";var o=n(0),i=n.n(o);i.a},function(t,e,n){e=t.exports=n(8)(!1),e.push([t.i,".vue-pull-to-wrapper[data-v-81faaf1a],\n.vue-pull-to-wrapper > .scroll-container[data-v-81faaf1a] {\n padding: 0;\n border: 0 none;\n margin: 0;\n}\n.vue-pull-to-wrapper[data-v-81faaf1a] {\n display: -webkit-box;\n display: -webkit-flex;\n display: flex;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -webkit-flex-direction: column;\n flex-direction: column;\n height: 100%;\n}\n.vue-pull-to-wrapper > .scroll-container[data-v-81faaf1a] {\n -webkit-box-flex: 1;\n -webkit-flex: 1;\n flex: 1;\n overflow-x: hidden;\n overflow-y: scroll;\n -webkit-overflow-scrolling: touch;\n}\n.vue-pull-to-wrapper > .scroll-container > .bottom-filler[data-v-81faaf1a] {\n height: 0px;\n}\n.vue-pull-to-wrapper > .action-block[data-v-81faaf1a] {\n position: relative;\n width: 100%;\n}\n.vue-pull-to-wrapper > .action-block > .default-text[data-v-81faaf1a] {\n height: 100%;\n line-height: 50px;\n text-align: center;\n}\n.vue-pull-to-wrapper[data-v-81faaf1a],\n.vue-pull-to-wrapper > .action-block-bottom[data-v-81faaf1a],\n.vue-pull-to-wrapper > .scroll-container > .bottom-fill[data-v-81faaf1a] {\n -webkit-transition-timing-function: cubic-bezier(0, 0, 0, 1);\n transition-timing-function: cubic-bezier(0, 0, 0, 1);\n}\n",""])},function(t,e,n){"use strict";function o(t,e){var n=t[1]||"",o=t[3];if(!o)return n;if(e&&"function"===typeof btoa){var r=i(o),s=o.sources.map((function(t){return"/*# sourceURL="+o.sourceRoot+t+" */"}));return[n].concat(s).concat([r]).join("\n")}return[n].join("\n")}function i(t){var e=btoa(unescape(encodeURIComponent(JSON.stringify(t)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,"+e;return"/*# "+n+" */"}t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var n=o(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n})).join("")},e.i=function(t,n){"string"===typeof t&&(t=[[null,t,""]]);for(var o={},i=0;i2&&void 0!==arguments[2]?arguments[2]:0;if(null==e)return t;var o,i="object"===("undefined"===typeof performance?"undefined":c()(performance))?performance:Date,r=null;return function(){var s=i.now();if(null!=r&&clearTimeout(r),o||(o=s),0!==n&&s-o>=n)t.apply(this,arguments),o=s;else{var a=this,c=Array.prototype.slice.call(arguments);r=setTimeout((function(){return r=null,t.apply(a,c)}),e)}}}var u=function(){var t=!1;try{window.addEventListener("test",e,{get passive(){return t=!0,!0}}),window.removeEventListener("test",e)}catch(n){t=!1}return t&&{passive:!0};function e(){}}();function f(t,e){var n=Object.create(t);return Object.assign(n,e),n}var d={pullText:"下拉刷新",triggerText:"释放更新",loadingText:"加载中...",doneText:"加载完成",failText:"加载失败",loadedStayTime:400,stayDistance:50,triggerDistance:70},h={pullText:"上拉加载",triggerText:"释放更新",loadingText:"加载中...",doneText:"加载完成",failText:"加载失败",loadedStayTime:400,stayDistance:50,triggerDistance:70},p="loaded-";function g(t,e,n,o){t.setProperty("transition-property",e||""),t.setProperty("transition-duration",n||""),t.setProperty("transition-delay",o||"")}function A(t){return"string"===typeof t&&t.startsWith(p)}function m(t,e){switch(e){case"pull":return t.pullText;case"trigger":return t.triggerText;case"loading":return t.loadingText;case"loaded-done":return t.doneText;default:return A(e)?t.failText:""}}var v={name:"vue-pull-to",props:{distanceIndex:{type:Number,default:2},topBlockHeight:{type:Number,default:50},bottomBlockHeight:{type:Number,default:50},wrapperHeight:{type:String,default:"100%"},topLoadMethod:Function,bottomLoadMethod:Function,isThrottleTopPull:{type:Boolean,default:!0},isThrottleBottomPull:{type:Boolean,default:!0},isThrottleScroll:{type:Boolean,default:!0},isTouchSensitive:{type:Boolean,default:!0},isScrollSensitive:{type:Boolean,default:!0},isTopBounce:{type:Boolean,default:!0},isBottomBounce:{type:Boolean,default:!0},isBottomKeepScroll:Boolean,topConfig:Object,bottomConfig:Object},data:function(){return{startY:null,startX:null,distance:0,diff:0,beforeDiff:0,state:"",shouldPullDown:!1,shouldPullUp:!1,shouldPassThroughEvent:!1,throttleEmitTopPull:null,throttleEmitBottomPull:null,throttleEmitScroll:null,throttleOnInfiniteScroll:null}},computed:{_topConfig:function(){return f(d,this.topConfig)},_bottomConfig:function(){return f(h,this.bottomConfig)},direction:{cache:!1,get:function(){var t=this.distance;return t>0?"down":t<0?"up":0}},topText:function(){return this.distance>0?m(this._topConfig,this.state):""},bottomText:function(){return this.distance<0?m(this._bottomConfig,this.state):""}},watch:{state:function(t){var e=this,n=this.distance,o=n>0?"top-state-change":"bottom-state-change";if(this.$emit(o,t),"string"!==typeof t||""===t);else if("loading"===t){var i=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"done",o=p+n;e.state=o,t=null};if(n>0?this.topLoadMethod(i):this.bottomLoadMethod(i),null===t)return;n>0?this.scrollTo(this._topConfig.stayDistance):this.scrollTo(-this._bottomConfig.stayDistance)}else if(A(t)&&null==this.startY){var r=n>0?this._topConfig:this._bottomConfig,s=this.$refs["bottom-filler"];if(s&&!(n>0)){var a=this.$refs["action-block-bottom"],c=this.diff;if(null!=a&&c<0){this.scrollTo(0,0);var l=a.style;l.setProperty("transform","translate(0, ".concat(c,"px)"));var u=s.style;u.setProperty("height","".concat(-c,"px")),this.$refs["scroll-container"].scrollTop-=c;var f="200ms",d="".concat(r.loadedStayTime,"ms");return g(l,"transform",f,d),g(u,"height",f,d),l.setProperty("transform","translate(0, 0)"),void u.setProperty("height","0px")}}this.scrollTo(0,200,r.loadedStayTime)}},isTouchSensitive:"updateTouchSensitivity",isScrollSensitive:"updateScrollSensitivity"},methods:{scrollTo:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:200,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;this.diff=t;var o=this.$refs["action-block-bottom"];if(null!=o){var i=o.style;i.getPropertyValue("transform")&&(g(i,"none"),i.setProperty("transform",""))}var r=this.$refs["bottom-filler"];if(null!=r){var s=r.style;s.getPropertyValue("height")&&(g(s,"none"),s.setProperty("height",""))}var a=this.$el.style;g(a,e>0||n>0?"transform":"none","".concat(e,"ms"),"".concat(n,"ms")),a.setProperty("transform","translate(0, ".concat(t,"px)"))},checkBottomReached:function(){var t=this.$refs["scroll-container"];return t.scrollTop+t.offsetHeight+1>=t.scrollHeight},handleTouchStart:function(t){var e=s()(t.touches,1),n=e[0];this.startY=n.clientY,this.startX=n.clientX,this.beforeDiff=this.diff;var o=this.$refs["scroll-container"];this.shouldPullDown=this.isTopBounce&&0===o.scrollTop,this.shouldPullUp=this.isBottomBounce&&this.checkBottomReached(),this.shouldPassThroughEvent=!1},handleTouchMove:function(t){var e=s()(t.touches,1),n=e[0],o=n.clientY,i=n.clientX,r=this.startY,a=this.startX,c=(o-r)/this.distanceIndex+this.beforeDiff,l=this.state;"loading"!==l||c*this.distance>0||(c=c<0?3e-308:-3e-308),this.distance=c;var u=this.shouldPassThroughEvent;if(Math.abs(o-r)0?this.shouldPullDown:this.shouldPullUp){var f;if(u||(t.preventDefault(),t.stopPropagation()),this.scrollTo(c,0),c>0){if(this.isThrottleTopPull?this.throttleEmitTopPull(this.diff):this.$emit("top-pull",this.diff),"function"!==typeof this.topLoadMethod)return;f=this._topConfig}else{if(this.isThrottleBottomPull?this.throttleEmitBottomPull(this.diff):this.$emit("bottom-pull",this.diff),"function"!==typeof this.bottomLoadMethod)return;f=this._bottomConfig}var d=Math.abs(c)1&&void 0!==arguments[1]?arguments[1]:0,o=arguments.length>2?arguments[2]:void 0;return l(t.$emit.bind(t,o),e,n)};this.throttleEmitTopPull=e(200,300,"top-pull"),this.throttleEmitBottomPull=e(200,300,"bottom-pull"),this.throttleEmitScroll=e(100,150,"scroll"),this.throttleOnInfiniteScroll=l((function(){t.checkBottomReached()&&t.$emit("infinite-scroll")}),400)},init:function(){this.createThrottleMethods(),this.bindEvents()}},mounted:function(){this.init()}},b=v;n(6);function y(t,e,n,o,i,r,s,a){var c,l="function"===typeof t?t.options:t;if(e&&(l.render=e,l.staticRenderFns=n,l._compiled=!0),o&&(l.functional=!0),r&&(l._scopeId="data-v-"+r),s?(c=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),i&&i.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(s)},l._ssrRegister=c):i&&(c=a?function(){i.call(this,this.$root.$options.shadowRoot)}:i),c)if(l.functional){l._injectStyles=c;var u=l.render;l.render=function(t,e){return c.call(e),u(t,e)}}else{var f=l.beforeCreate;l.beforeCreate=f?[].concat(f,c):[c]}return{exports:t,options:l}}var C=y(b,o,i,!1,null,"81faaf1a",null);C.options.__file="src/vue-pull-to.vue";var x=C.exports;e["default"]=x},function(t,e,n){"use strict";function o(t,e){for(var n=[],o={},i=0;in.parts.length&&(o.parts.length=n.parts.length)}else{var s=[];for(i=0;i0&&(!S.multiline||S.multiline&&"\n"!==A(w,S.lastIndex-1))&&(D="(?: "+D+")",P=" "+P,U++),n=new RegExp("^(?:"+D+")",T)),x&&(n=new RegExp("^"+D+"$(?!\\s)",T)),y&&(i=S.lastIndex),a=o(p,k?n:S,P),k?a?(a.input=b(a.input,U),a[0]=b(a[0],U),a.index=S.lastIndex,S.lastIndex+=a[0].length):S.lastIndex=0:y&&a&&(S.lastIndex=S.global?a.index+a[0].length:i),x&&a&&a.length>1&&o(h,a[0],n,(function(){for(c=1;cB;B++)if((h||B in C)&&(v=C[B],b=x(v,B,y),t))if(e)I[B]=b;else if(b)switch(t){case 3:return!0;case 5:return v;case 6:return B;case 2:l(I,v)}else switch(t){case 4:return!1;case 7:l(I,v)}return f?-1:i||u?u:I}};t.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6),filterReject:u(7)}},be50:function(t,e,n){"use strict";n("7450")},cf68:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyBAMAAADsEZWCAAAAD1BMVEXm5ubo6Ojp6enr6+vt7e1FnZagAAACrklEQVQ4yx1SixUbMQgT3AKAFwDcAfzpBN1/qMrJS5w7bCQhC6IGSUGYQJd6Ox9ZPXi1AGJBavhUTT0JjYPGAab9WcDYIxsmlnxkayX8mhxCmKHA75az5cfRbWybEExiu08xDSgGym0mwuf3j4SvHeQxDJJzh2zp4iOlrD8iOb4SXyC1wiOLRTcnrje+nGamFeXVKWkmzbFIPChkmJ6Fg7mBpV8n+JGOVCd4jv1thThkjeQGNeafpeV3rsEWLfyWc8tC9jOv6FQ8rRzHOOVB+jCYEUAJpDvh8xHNFm/Tm5p5lw94Pp3NhtKEfQsGvnXhowdZE73hPwxKvjDd4i4PCdd0fe3W5fO8ktAsUAacLgstpUw60JCiPLg2XpkgiqPIYYXJd9ksGIT3q+LlevypzItvO+s0F1dBzVr2QDMUkYmuyGcrIS44mVJ7JVKwQXjYuBYp0Uetecbswzsikzu3gUR8bJC/C8Gd/NAzI/xdUGOYQQHDZ8X2d5XuzGRUiXAi9si5CRgoiToRZPtzLJkd0FUHRHZwJf0BHT1sE7gcnh0jmKKlSSF4/GBirGk5+K9NKlGDCfc9JtPhg78JdabH0YQRKNZnJ8tFnPfXHJb4xum1TTCeEmyEdbyEJLjznMLHuFD2Y9NEkSleIBs7SiCbblhgctVi9ch++kDYnn1C9DA5TvdPsToXM55wI6k+8eKT1blwPTqWb5CFJ+7dTBmab+KHy+xwNtItXhZNSpHD2fxnynrxG3ZBKRe8KBpXk11AnadlccEhr9w1nBBvBylNkv7A8eqpGBCDqhitmWQXBjjdS6idr/QjXWLDeMzMbVDoJuM8zN7WenMZWXgZ2vX3F01J3jHZbwk1LRP+DWEvDJtOUoh/AIaBUz5VpWyhuyx4QtgL/NmgC6kM/JvNe+R/C/5aL7BKIbYAAAAASUVORK5CYII="},d0e3:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXh7eHl8eXj7+Pn8+eTbH1KAAACPElEQVQozxWPQWrbQABF/0xn3JFKQRTZOIuUsbCCbOgdRoYEOauxkYPcTRyTlPQWIxEltrsRwQ6hK9nEQek6F+gNTE/Q3qLLusv34cN7SH3mFicdYW4gNIhJWXPBRVXzjcFD0IqeU4o4PRbAIVjyico0vJpIifqPfL80QN9DAQY5ucRHE/hpHxBldXe9GilaHKcKMlj6pho2zXgkNdBl0oJ8kiF1DSiJF1ZHBJkQr0Dbux/5I42Zp4cFahJDFGeW6/QjBwmFY/Q7vZ2SnoOdW2parv/Cnm81+m0xrEfiVXQ3W4nOXIqVYi3l6AAQBwMFkViVBANMto4enXHPNTkHBB0oVj4r5vHzCWayrgBvxtygDlDB2CNDjd80ZInY69aKVYZcfJ8DW+fWuc+syEODALx+ojqoafHsthTI+ZW27PGpIeo/cR6YKcbqIuIFhHmBrzAovzIOOJk1ucvcDzrMRYGVBH2yvcAOf0KiKwfRovBI3tm/kW1eemtfNWwIIXE2mJNhvoszfmMBfRCv0OPwd2321uDW3nx2q/BDxFVeoN1g7a6Im8yRnoawa8kbdXnU0cHeTMxKfZGlJgvLb3sKsxgglQnDdAfvj9LUnqWRDo0GiUmPwyU7TAsD7wHeIW3Nfy1qVGKoE9NgJCdYCAexNRob9yCn4DAQmXtQuUtera6bEmTTXhZy6h856xi4mnEl6BI9mfISkLbtJyZIMJIAUd5ZOBEu88KRAk71yxfItj/hpIB0Errv4gO1os4/UICf+o3kkqwAAAAASUVORK5CYII="},d28b:function(t,e,n){var o=n("746f");o("iterator")},d784:function(t,e,n){"use strict";n("ac1f");var o=n("e330"),i=n("6eeb"),r=n("9263"),s=n("d039"),a=n("b622"),c=n("9112"),l=a("species"),u=RegExp.prototype;t.exports=function(t,e,n,f){var d=a(t),h=!s((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),p=h&&!s((function(){var e=!1,n=/a/;return"split"===t&&(n={},n.constructor={},n.constructor[l]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return e=!0,null},n[d](""),!e}));if(!h||!p||n){var g=o(/./[d]),A=e(d,""[t],(function(t,e,n,i,s){var a=o(t),c=e.exec;return c===r||c===u.exec?h&&!s?{done:!0,value:g(e,n,i)}:{done:!0,value:a(n,e,i)}:{done:!1}}));i(String.prototype,t,A[0]),i(u,d,A[1])}f&&c(u[d],"sham",!0)}},d81d:function(t,e,n){"use strict";var o=n("23e7"),i=n("b727").map,r=n("1dde"),s=r("map");o({target:"Array",proto:!0,forced:!s},{map:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}})},df5e:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAATlBMVEXdzaHh0KPgz6LdzKDezqLczJ7ezZ/fz6Dcy5zi0aXdzZ3fz6Tfz57h0KDg0aLcyZrg0KXi0qPfzZ3j06bh0qbdyJbfzJrhz5/cxpLZwo0vDconAAAFn0lEQVRIxxyPW5LjMAwDAT5FybLl2JnM3P+i6+wXWVC1GoQGaD0h4XM3Q5o4T0HgABHBi6pZ4CDXXcUOFd6VhqC3Kch4EI8w9oMXwvU6m5LOOvcxKMOhuu8i5+5cMjcgb0t4F2uvOoeI3/MlT4IqsbtM9UG2AGSXUOsxzPevnXzK1CSHytZLvx7VdQmUcJsJCxJh2nmHW12Qod1qPjt8pih47uQ9aGpoNWF+yElCt60oH7vdIU/MnlRPSBLC/VwqxcKR8PFqnADN9ih5ufqnTlG9KwCofvs7kKYqOPHTNMQ93j9qNImFw9vjHPZ0F1m8hUUVB/Q/TrRYDMXr9++APMFARAt6sPh6wVAXzxUGhZsFUwCNfPZ8/72TAHebAhvuOuT3gO1Vn5d9Jd5sBRkg0p2seL9B7ulkjFJFIt9HPpLzdSzzMP3UcodAfMqC6pBuET2heHK1itZf1GZ1bi0BwOSxiCS8f/JBHMPMM4XCu3Mt1uz9lJbDJRqsKDZuikzkvskQEz6hanfDfO494azY5JpqPqOF1RhxD9XYEdaNxiqWqakKgmPfmrsta8KAiwF4HBxGVUJAgeSqQaiRRZJ7D2jedhw5t1CIAKxag0CBA60BpoBE6DcUi8O5AuM4pLfN0kHLmeu2B4e6HofqbgxsTWUw3PAODqa1oDtyzgXBlusi1KFdclMPE8O3jvLJ8RNi5/RxDQVzVmXA233XQ4KummunfxvLOZo+iH37964YjP06995CTdu9hsvErqJNzmf4wTrZ5DL7+qW9EoLnadrx67b8dUtrJnBXaT1N1uvPaYRKpWkq52xNsMN7vv4Sdryt/f4MhQoMCKnvVxikai1CQ6ZsnwJDc8+3Y/z8HcfvYQNq66pnAu1Hwa+3KNSwbNu8h3nDPqTl9fl7tx8fBhFfdS0o0F3JUKEZtZG9b/LZEM95lzaR30OnWPzroMxyZYdBIMoMnpN0J+m7/40+/P4soFSUjgzE7yY5zrMJuoZv0CmpVguYx1pprfb5HOviRVhHUVi/352shxCYrYBZxGtVaxiAz/MsaGSIsB7R1t4zJXH//n7RTTQQwxqcGEqEvklFHUgiO2GvJV+jAIPR+N29usWDoiSOVrN3XuqT1egQJAAU9EwslVJC8u0rGcy+WPqktJhjfMpatIG6CDAb0v5H34MGKqiVRue7GGLZ9Otxtt4JIrAhxBDwDuqI9JavcO0A7GlqFt219tH/bln9jBXzaKWAEqJV0CBxs5TwM8EvUPHaa8S86vN303MVWOsl3goDBHPWSoQ9c0kQmCKljfsKNH1+ofEOHW8a9a7glZGS8fPieL/SRSs0LAhI4FDTnXs1QYtubv2+IXPZpHB4bhivRexBkYKsSrYXNjvMUbVXpVJ+N6haV72c1k2zrnv5IYBMJBYTSZx0KTkoM3vY93rU/qs7zHplc/3d2ACadhFWByrn9LUk2IWb5JywvawTQc3F0iz+lgsBmInAIemBJtft2plKIlAFOgcroigrG2XlDsAzywQECNyaI8yr2ogoh7D4qJOYmZBzQgoZAM1PAcB8sDrr1uE5CDMR+nWSSVUGUCHAs8Vd21HOE0FzNj37pX0sLp9p3K8k++xxpkmzDxK64rmTSJnDUuIgTeslui6lg92jonZXI4jqNiUuzN4IagcKMjCniMGCODoo8T4tGDprn2hRww+NrnYiCwokd9iiWrkmbRfXYGLAoZrjO1lVQKExjUy5fIkgJURmz2uGFdASwwlWx5gDVTMK7hP6ISRVsFbYNmqtZL9MQtio285PaekyzDhZmtdexCYB0SZcTmBdhvdbmAEonk8hwcHQuZN1kVqrhyKoHHsnQhQAjF7SG533Da2S4LGjx1LoZqp7XeKQLDUBmYmydG0NQHpMeR5lRIRQc1PQ2ASMQflF4YBDMt0/GFlEHeRwCcEAAAAASUVORK5CYII="},e01a:function(t,e,n){"use strict";var o=n("23e7"),i=n("83ab"),r=n("da84"),s=n("e330"),a=n("1a2d"),c=n("1626"),l=n("3a9b"),u=n("577e"),f=n("9bf2").f,d=n("e893"),h=r.Symbol,p=h&&h.prototype;if(i&&c(h)&&(!("description"in p)||void 0!==h().description)){var g={},A=function(){var t=arguments.length<1||void 0===arguments[0]?void 0:u(arguments[0]),e=l(p,this)?new h(t):void 0===t?h():h(t);return""===t&&(g[e]=!0),e};d(A,h),A.prototype=p,p.constructor=A;var m="Symbol(test)"==String(h("test")),v=s(p.toString),b=s(p.valueOf),y=/^Symbol\((.*)\)[^)]+$/,C=s("".replace),x=s("".slice);f(p,"description",{configurable:!0,get:function(){var t=b(this),e=v(t);if(a(g,t))return"";var n=m?x(e,7,-1):C(e,y,"$1");return""===n?void 0:n}}),o({global:!0,forced:!0},{Symbol:A})}},e160:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEX6+fP8+/X+/ff///kbczPAAAACeElEQVQozxXHQUgUUQAG4P8936yzs6VvZNZmN9QxVxiF9OLBoOjtOC6rQq6ygXjI2fCQBdXBg4egtzFGdqkoI+zgBFbqkm3hQSxhFYLotOcubeKhOnVYoqQy+m4f5g5TvpX0xHLbLY9j8SMhJp+Jk4LfAUS2kVRIjILmnwGBTX42PhCVlDJQkIiy2nWAvaJ1h+oFIpJ0hMSYVbyyrgDWshcMpMyL1brPDQKWmduO+KTJ6XeXAMK9Yc3FpD7atyNwg6kt5XgFpLPhjUTFSYVn2abDiugGShwD8JTVRJVo/2ecuKtRb/qc4BK+9TboFfokog4T2Fn6Oqdnsjk90NMS76Rji6E0NmwkPBAZ4Xbkw8KoDAkAbEhkc78e9omxxgxg6qa5HvMv+UZbCV0qmHnSHKl5TxeA2XTCGWekR581mwC5crBH81PznASqB9va3TbkYAjJPLfg5uBfXaJgIgIBv9eessRIhxe7PA7kj6uUMeMaQ/OEQOYRaaHlqH2Gxwsl6E/pwVY5FH7uCypBZPKvDQyVziYBrAkMURe2MOOOxG/eQpp5PF+bFzUV5HtPj9GeiVSNZDELleifYTp9NAjsoiXg4cW+4ZORkdSMB/B74aAdjhsVakhgkugsbmqcDSLEoWp8zRjrux3tli6Q5uM3E+maT99Wy0RiP7tboiuRZle2c6CYeL2kcUc1KvPtQKucogMadKVTQOJYCeyCYlhQQ/Q7Etfd/vBygy9iqy+LyHeF46saCYvW6ingsbA9RBWtdi8GgUXW+oQx9/wP6bAAX1TWeV+CbShZDlQ9xT6SoSxZmKRAkmXb60kzEzkRF+Ccb94BGspGJoN/UzmyR4wjXHAAAAAASUVORK5CYII="},e3cf:function(t,e,n){"use strict";n("04aa")},e538:function(t,e,n){var o=n("b622");e.f=o},e9c4:function(t,e,n){var o=n("23e7"),i=n("da84"),r=n("d066"),s=n("2ba4"),a=n("e330"),c=n("d039"),l=i.Array,u=r("JSON","stringify"),f=a(/./.exec),d=a("".charAt),h=a("".charCodeAt),p=a("".replace),g=a(1..toString),A=/[\uD800-\uDFFF]/g,m=/^[\uD800-\uDBFF]$/,v=/^[\uDC00-\uDFFF]$/,b=function(t,e,n){var o=d(n,e-1),i=d(n,e+1);return f(m,t)&&!f(v,i)||f(v,t)&&!f(m,o)?"\\u"+g(h(t,0),16):t},y=c((function(){return'"\\udf06\\ud834"'!==u("\udf06\ud834")||'"\\udead"'!==u("\udead")}));u&&o({target:"JSON",stat:!0,forced:y},{stringify:function(t,e,n){for(var o=0,i=arguments.length,r=l(i);ob)","g");return"b"!==t.exec("b").groups.a||"bc"!=="b".replace(t,"$c")}))},1276:function(t,e,n){"use strict";var o=n("2ba4"),i=n("c65b"),r=n("e330"),s=n("d784"),a=n("44e7"),c=n("825a"),l=n("1d80"),u=n("4840"),f=n("8aa5"),d=n("50c4"),h=n("577e"),p=n("dc4a"),g=n("4dae"),A=n("14c3"),m=n("9263"),v=n("9f7f"),b=n("d039"),y=v.UNSUPPORTED_Y,C=4294967295,x=Math.min,S=[].push,B=r(/./.exec),w=r(S),I=r("".slice),E=!b((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));s("split",(function(t,e,n){var r;return r="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,n){var r=h(l(this)),s=void 0===n?C:n>>>0;if(0===s)return[];if(void 0===t)return[r];if(!a(t))return i(e,r,t,s);var c,u,f,d=[],p=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),A=0,v=new RegExp(t.source,p+"g");while(c=i(m,v,r)){if(u=v.lastIndex,u>A&&(w(d,I(r,A,c.index)),c.length>1&&c.index=s))break;v.lastIndex===c.index&&v.lastIndex++}return A===r.length?!f&&B(v,"")||w(d,""):w(d,I(r,A)),d.length>s?g(d,0,s):d}:"0".split(void 0,0).length?function(t,n){return void 0===t&&0===n?[]:i(e,this,t,n)}:e,[function(e,n){var o=l(this),s=void 0==e?void 0:p(e,t);return s?i(s,e,o,n):i(r,h(o),e,n)},function(t,o){var i=c(this),s=h(t),a=n(r,i,s,o,r!==e);if(a.done)return a.value;var l=u(i,RegExp),p=i.unicode,g=(i.ignoreCase?"i":"")+(i.multiline?"m":"")+(i.unicode?"u":"")+(y?"g":"y"),m=new l(y?"^(?:"+i.source+")":i,g),v=void 0===o?C:o>>>0;if(0===v)return[];if(0===s.length)return null===A(m,s)?[s]:[];var b=0,S=0,B=[];while(S1&&void 0!==arguments[1]?arguments[1]:{};switch(l=d.duration||1e3,i=d.offset||0,p=d.callback,r=d.easing||u,s=d.a11y||!1,a(d.container)){case"object":t=d.container;break;case"string":t=document.querySelector(d.container);break;default:t=window}switch(n=g(),a(f)){case"number":e=void 0,s=!1,o=n+f;break;case"object":e=f,o=A(e);break;case"string":e=document.querySelector(f),o=A(e);break}switch(c=o-n+i,a(d.duration)){case"number":l=d.duration;break;case"function":l=d.duration(c);break}requestAnimationFrame(v)}return y},d=f(),h=d,p=n("7286"),g=n.n(p),A=n("477e"),m=n.n(A),v=n("e160"),b=n.n(v),y=n("df5e"),C=n.n(y),x=n("ec0f"),S=n.n(x),B=n("b671"),w=n.n(B),I=n("5629"),E=n.n(I),k=n("d0e3"),T=n.n(k),D=n("4039"),U=n.n(D),P=n("1e75"),O=n.n(P),R=n("1632"),Q=n.n(R),V=n("7abd"),M=n.n(V),N=n("356c"),F=n.n(N),L=n("b165"),K=n.n(L),H=n("cf68"),W=n.n(H),J=n("4400"),z=n.n(J),Y=n("802e"),j=n.n(Y),G=n("0827"),q=n.n(G),Z={themes:[{body:"#ede7da url("+g.a+") repeat",content:"#ede7da url("+m.a+") repeat",popup:"#ede7da url("+b.a+") repeat"},{body:"#ede7da url("+C.a+") repeat",content:"#ede7da url("+S.a+") repeat",popup:"#ede7da url("+w.a+") repeat"},{body:"#ede7da url("+E.a+") repeat",content:"#ede7da url("+T.a+") repeat",popup:"#ede7da url("+U.a+") repeat"},{body:"#ede7da url("+O.a+") repeat",content:"#ede7da url("+Q.a+") repeat",popup:"#ede7da url("+M.a+") repeat"},{body:"#ebcece repeat",content:"#f5e4e4 repeat",popup:"#faeceb repeat"},{body:"#ede7da url("+F.a+") repeat",content:"#ede7da url("+K.a+") repeat",popup:"#ede7da url("+W.a+") repeat"},{body:"#ede7da url("+z.a+") repeat",content:"#ede7da url("+j.a+") repeat",popup:"#ede7da url("+q.a+") repeat"}],fonts:[{fontFamily:"Microsoft YaHei, PingFangSC-Regular, HelveticaNeue-Light, Helvetica Neue Light, sans-serif"},{fontFamily:"PingFangSC-Regular, -apple-system, Simsun"},{fontFamily:"Kaiti"}]},X=Z,$=(n("05b3"),{name:"PopCata",data:function(){return{isNight:6==this.$store.state.config.theme,index:this.$store.state.readingBook.index}},computed:{catalog:function(){return this.$store.state.readingBook.catalog},popCataVisible:function(){return this.$store.state.popCataVisible},theme:function(){return this.$store.state.config.theme},popupTheme:function(){return{background:X.themes[this.theme].popup}}},mounted:function(){},watch:{theme:function(t){this.isNight=6==t},popCataVisible:function(){this.$nextTick((function(){var t=this.$store.state.readingBook.index,e=this.$refs.cataData;h(this.$refs.cata[t],{container:e,duration:0})}))}},methods:{isSelected:function(t){return t==this.$store.state.readingBook.index},gotoChapter:function(t){this.index=this.catalog.indexOf(t),this.$store.commit("setPopCataVisible",!1),this.$store.commit("setContentLoading",!0),this.$emit("getContent",this.index)}}}),_=$,tt=(n("635f"),n("2877")),et=Object(tt["a"])(_,r,s,!1,null,"0aacaab8",null),nt=et.exports,ot=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"settings-wrapper",class:{night:t.isNight,day:!t.isNight},style:t.popupTheme},[n("div",{staticClass:"settings-title"},[t._v("设置")]),n("div",{staticClass:"setting-list"},[n("ul",[n("li",{staticClass:"theme-list"},[n("i",[t._v("阅读主题")]),t._l(t.themeColors,(function(e,o){return n("span",{key:o,ref:"themes",refInFor:!0,staticClass:"theme-item",class:{selected:t.selectedTheme==o},style:e,on:{click:function(e){return t.setTheme(o)}}},[o<6?n("em",{staticClass:"iconfont"},[t._v("")]):n("em",{staticClass:"moon-icon"},[t._v(t._s(t.moonIcon))])])}))],2),n("li",{staticClass:"font-list"},[n("i",[t._v("正文字体")]),t._l(t.fonts,(function(e,o){return n("span",{key:o,staticClass:"font-item",class:{selected:t.selectedFont==o},on:{click:function(e){return t.setFont(o)}}},[t._v(t._s(e))])}))],2),n("li",{staticClass:"font-size"},[n("i",[t._v("字体大小")]),n("div",{staticClass:"resize"},[n("span",{staticClass:"less",on:{click:t.lessFontSize}},[n("em",{staticClass:"iconfont"},[t._v("")])]),n("b"),t._v(" "),n("span",{staticClass:"lang"},[t._v(t._s(t.fontSize))]),n("b"),n("span",{staticClass:"more",on:{click:t.moreFontSize}},[n("em",{staticClass:"iconfont"},[t._v("")])])])]),t.$store.state.miniInterface?t._e():n("li",{staticClass:"read-width"},[n("i",[t._v("页面宽度")]),n("div",{staticClass:"resize"},[n("span",{staticClass:"less",on:{click:t.lessReadWidth}},[n("em",{staticClass:"iconfont"},[t._v("")])]),n("b"),t._v(" "),n("span",{staticClass:"lang"},[t._v(t._s(t.readWidth))]),n("b"),n("span",{staticClass:"more",on:{click:t.moreReadWidth}},[n("em",{staticClass:"iconfont"},[t._v("")])])])])])])])},it=[],rt=(n("82da"),n("b3f5")),st={name:"ReadSettings",data:function(){return{theme:0,isNight:6==this.$store.state.config.theme,moonIcon:"",themeColors:[{background:"rgba(250, 245, 235, 0.8)"},{background:"rgba(245, 234, 204, 0.8)"},{background:"rgba(230, 242, 230, 0.8)"},{background:"rgba(228, 241, 245, 0.8)"},{background:"rgba(245, 228, 228, 0.8)"},{background:"rgba(224, 224, 224, 0.8)"},{background:"rgba(0, 0, 0, 0.5)"}],moonIconStyle:{display:"inline",color:"rgba(255,255,255,0.2)"},fonts:["雅黑","宋体","楷书"]}},mounted:function(){var t=this.$store.state.config;this.theme=t.theme,6==this.theme?this.moonIcon="":this.moonIcon=""},computed:{config:function(){return this.$store.state.config},popupTheme:function(){return{background:X.themes[this.config.theme].popup}},selectedTheme:function(){return this.$store.state.config.theme},selectedFont:function(){return this.$store.state.config.font},fontSize:function(){return this.$store.state.config.fontSize},readWidth:function(){return this.$store.state.config.readWidth}},methods:{setTheme:function(t){6==t?(this.isNight=!0,this.moonIcon="",this.moonIconStyle.color="#ed4259"):(this.isNight=!1,this.moonIcon="",this.moonIconStyle.color="rgba(255,255,255,0.2)");var e=this.config;e.theme=t,this.$store.commit("setConfig",e),this.uploadConfig()},setFont:function(t){var e=this.config;e.font=t,this.$store.commit("setConfig",e),this.uploadConfig()},moreFontSize:function(){var t=this.config;t.fontSize<48&&(t.fontSize+=2),this.$store.commit("setConfig",t),this.uploadConfig()},lessFontSize:function(){var t=this.config;t.fontSize>12&&(t.fontSize-=2),this.$store.commit("setConfig",t),this.uploadConfig()},moreReadWidth:function(){var t=this.config;t.readWidth<960&&(t.readWidth+=160),this.$store.commit("setConfig",t),this.uploadConfig()},lessReadWidth:function(){var t=this.config;t.readWidth>640&&(t.readWidth-=160),this.$store.commit("setConfig",t),this.uploadConfig()},uploadConfig:function(){rt["a"].post("/saveReadConfig",this.config)}}},at=st,ct=(n("0928"),Object(tt["a"])(at,ot,it,!1,null,"65e7f0f4",null)),lt=ct.exports,ut=(n("d81d"),n("00b4"),n("466d"),{name:"pcontent",data:function(){return{}},props:["carray"],render:function(){var t=this,e=arguments[0],n=this.fontFamily,o=this.fontSize,i=n;return i.fontSize=o,this.show?e("div",[this.carray.map((function(n){return/]*src/.test(n)?e("img",{directives:[{name:"lazy",value:t.proxyImage(n)}]}):e("p",{style:i,domProps:{innerHTML:n}})}))]):e("div")},computed:{show:function(){return this.$store.state.showContent},fontFamily:function(){return X.fonts[this.$store.state.config.font]},fontSize:function(){return this.$store.state.config.fontSize+"px"}},methods:{proxyImage:function(t){var e=/]*src="([^"]*(?:"[^>]+\})?)"[^>]*>/,n=t.match(e)[1];return/^data:/.test(n)?n:"../../image?path="+encodeURIComponent(n)+"&url="+encodeURIComponent(sessionStorage.getItem("bookUrl"))+"&width="+this.$store.state.config.readWidth}},watch:{fontSize:function(){var t=this;t.$store.commit("setShowContent",!1),this.$nextTick((function(){t.$store.commit("setShowContent",!0)}))}}}),ft=ut,dt=(n("e3cf"),Object(tt["a"])(ft,c,l,!1,null,"4684738b",null)),ht=dt.exports,pt=n("897d"),gt=n.n(pt),At={components:{PopCata:nt,Pcontent:ht,ReadSettings:lt,PullTo:gt.a},created:function(){var t=JSON.parse(localStorage.getItem("config"));null!=t&&this.$store.commit("setConfig",t)},beforeCreate:function(){var t=JSON.parse(localStorage.getItem("config"));null!=t&&this.$store.commit("setConfig",t)},mounted:function(){var t=this;this.loading=this.$loading({target:this.$refs.content,lock:!0,text:"正在获取内容",spinner:"el-icon-loading",background:"rgba(0,0,0,0)"});var e=this,n=sessionStorage.getItem("bookUrl"),o=sessionStorage.getItem("bookName"),i=sessionStorage.getItem("chapterIndex")||0,r=JSON.parse(localStorage.getItem(n));(null==r||i>0)&&(r={bookName:o,bookUrl:n,index:i},localStorage.setItem(n,JSON.stringify(r))),this.getCatalog(n).then((function(n){var o=n.data.data;r.catalog=o,e.$store.commit("setReadingBook",r);var i=e.$store.state.readingBook.index||0;t.getContent(i),window.addEventListener("keyup",t.handleKeyPress),window.addEventListener("scroll",t.handleScroll)}),(function(t){throw e.loading.close(),e.$message.error("获取书籍目录失败"),t}))},destroyed:function(){window.removeEventListener("keyup",this.handleKeyPress),window.removeEventListener("scroll",this.handleScroll),this.readSettingsVisible=!1,this.popCataVisible=!1},watch:{title:function(){document.title=sessionStorage.getItem("bookName")+" | "+this.title},content:function(){var t=this;this.$store.commit("setContentLoading",!1),setTimeout((function(){return t.handleScroll()}),500)},theme:function(t){this.isNight=6==t},bodyColor:function(t){this.bodyTheme.background=t},chapterColor:function(t){this.chapterTheme.background=t},readWidth:function(t){this.chapterTheme.width=t;var e=-((parseInt(t)+130)/2+68)+"px",n=-((parseInt(t)+130)/2+52)+"px";this.leftBarTheme.marginLeft=e,this.rightBarTheme.marginRight=n},popupColor:function(t){this.leftBarTheme.background=t,this.rightBarTheme.background=t},readSettingsVisible:function(t){if(!t){var e=JSON.stringify(this.$store.state.config);localStorage.setItem("config",e)}}},data:function(){return{title:"",content:[],noPoint:!0,showToolBar:!1,onTop:!0,onBottom:!1,topConfig:{pullText:"加载上一章",triggerText:"松开加载上一章"},bottomConfig:{pullText:"加载下一章",triggerText:"松开加载下一章"}}},computed:{catalog:function(){return this.$store.state.catalog},windowHeight:function(){return window.innerHeight},contentHeight:function(){return this.$refs.content.offsetHeight},popCataVisible:{get:function(){return this.$store.state.popCataVisible},set:function(t){this.$store.commit("setPopCataVisible",t)}},readSettingsVisible:{get:function(){return this.$store.state.readSettingsVisible},set:function(t){this.$store.commit("setReadSettingsVisible",t)}},config:function(){return this.$store.state.config},theme:function(){return this.config.theme},bodyColor:function(){return X.themes[this.config.theme].body},chapterColor:function(){return X.themes[this.config.theme].content},popupColor:function(){return X.themes[this.config.theme].popup},isNight:function(){return 6==this.$store.state.config.theme},readWidth:function(){return this.$store.state.miniInterface?window.innerWidth+"px":this.$store.state.config.readWidth-130+"px"},popupWidth:function(){return this.$store.state.miniInterface?window.innerWidth-33:this.$store.state.config.readWidth-33},bodyTheme:function(){return{background:X.themes[this.$store.state.config.theme].body}},chapterTheme:function(){return{background:X.themes[this.$store.state.config.theme].content,width:this.readWidth}},leftBarTheme:function(){return{background:X.themes[this.$store.state.config.theme].popup,marginLeft:this.$store.state.miniInterface?0:-(this.$store.state.config.readWidth/2+68)+"px",display:this.$store.state.miniInterface&&!this.showToolBar?"none":"block"}},rightBarTheme:function(){return{background:X.themes[this.$store.state.config.theme].popup,marginRight:this.$store.state.miniInterface?0:-(this.$store.state.config.readWidth/2+52)+"px",display:this.$store.state.miniInterface&&!this.showToolBar?"none":"block"}},show:function(){return this.$store.state.showContent}},methods:{getCatalog:function(t){return rt["a"].get("/getChapterList?url="+encodeURIComponent(t))},getContent:function(t){var e=this;this.$store.commit("setShowContent",!1),this.loading.visible||(this.loading=this.$loading({target:this.$refs.content,lock:!0,text:"正在获取内容",spinner:"el-icon-loading",background:"rgba(0,0,0,0)"}));var n=sessionStorage.getItem("bookUrl"),o=JSON.parse(localStorage.getItem(n));o.index=t,localStorage.setItem(n,JSON.stringify(o)),this.$store.state.readingBook.index=t,sessionStorage.setItem("chapterIndex",t);var i=this.$store.state.readingBook.catalog[t].title,r=this.$store.state.readingBook.catalog[t].index;this.title=i,h(this.$refs.top,{duration:0});var s=this;rt["a"].get("/getBookContent?url="+encodeURIComponent(n)+"&index="+r).then((function(t){if(t.data.isSuccess){var n=t.data.data;s.content=n.split(/\n+/)}else s.$message.error("书源正文解析错误!"),s.content=["书源正文解析失败!"];if(e.$store.commit("setContentLoading",!0),s.loading.close(),s.noPoint=!1,s.$store.commit("setShowContent",!0),!t.data.isSuccess)throw t.data}),(function(t){throw s.$message.error("获取章节内容失败"),s.content=["获取章节内容失败!"],s.loading.close(),s.$store.commit("setShowContent",!0),t}))},toTop:function(){h(this.$refs.top)},toBottom:function(){h(this.$refs.bottom)},toNextChapter:function(t){this.$store.commit("setContentLoading",!0);var e=this.$store.state.readingBook.index;e++,"function"===typeof t&&t("done"),"undefined"!==typeof this.$store.state.readingBook.catalog[e]?(this.$message.info("下一章"),this.getContent(e)):this.$message.error("本章是最后一章")},toLastChapter:function(t){this.$store.commit("setContentLoading",!0);var e=this.$store.state.readingBook.index;e--,"function"===typeof t&&t("done"),"undefined"!==typeof this.$store.state.readingBook.catalog[e]?(this.$message.info("上一章"),this.getContent(e)):this.$message.error("本章是第一章")},toShelf:function(){this.$router.push("/")},handleKeyPress:function(t){switch(t.key){case"ArrowLeft":t.stopPropagation(),t.preventDefault(),this.toLastChapter();break;case"ArrowRight":t.stopPropagation(),t.preventDefault(),this.toNextChapter();break;case"ArrowUp":t.stopPropagation(),t.preventDefault(),0===document.documentElement.scrollTop?this.$message.warning("已到达页面顶部"):h(0-document.documentElement.clientHeight+100);break;case"ArrowDown":t.stopPropagation(),t.preventDefault(),document.documentElement.clientHeight+document.documentElement.scrollTop===document.documentElement.scrollHeight?this.$message.warning("已到达页面底部"):h(document.documentElement.clientHeight-100);break}},handleScroll:function(){var t=document.documentElement;this.onTop=0===t.scrollTop,this.onBottom=t.scrollTop+t.clientHeight>=t.scrollHeight}}},mt=At,vt=(n("c0aa"),Object(tt["a"])(mt,o,i,!1,null,"3a303318",null));e["default"]=vt.exports},5629:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXN383Q4tDP4c/R5NEInCCXAAACVElEQVQozw3Hv2sTYRwH4M/79pJ7bZL2bXqtERJ97zjUpbZDhg6pfC8qibi8hLR0EaJ0EFxaCSWDxjfpj1zrYBcRBKE6SAfBJWsx9i8IQfdQxDlKtA6t2OnhQfN3lbG7ytYRywF8rVoPCNO0X2sQOKDpAnSDK2VwkHgmh5yLGT8qASt+2KofnNt2Xg1gf1UF8AoM6052cRMNaloLZb7RKQGrKKji2OefsZF+VqIvos5ZLVIZCX61JcwUdk56wASVkgQvzPfvmT2twTSwyYaC/Pl/UhAHorFhBgZtL6XdAZRp1tkPwC1NLa9CWs5prLhI85NBQsLdXvjDymG3/EbYfQhVNYqc3TtktQhWLY3ko0QsdMbSEp+64v0NfxyqLbIGdh6M2xHHlLBGqKTyQo4E/nebBgBfe1GpdeywYXc8CT7D3cKXuMXkBy4xN6o5OuKamYp3DVI6uccO9lxgd2CAlJgI2BGgaAgIJV/TYwKqu3WFccjbMuA+bVkWgS2bfnlRbD1Eb1sDyWMmjKYIBgGAWbqKRicfvzBkBIz3V5AKnguWdglQEysQsSuVzOg6ALy1pitA5ykGCsc857BRYcgCSZyFOdvoOigSGoPc5Ta73mgxshIcQE5sHMHd9D7yqITw7JO+GHVMxjhzYLcKPSEgmz3fU+BRy3iYNtiXLaBssCW8KguReqkQOTb3MStV0Ugt4U1eIs1RZWRII6Ww8xeNNItyGGQI4ZMlpg/3lQtkl2JFnBp1imRyFe0kK2Id3PCslMgiQNMS77gvFeDhG3cSkYvheeg/e7ClIh5oh+IAAAAASUVORK5CYII="},"635f":function(t,e,n){"use strict";n("6c5b")},"6c5b":function(t,e,n){},7286:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXr5djn4dTp49bt59rT6LKxAAACnElEQVQozw3NUUwScRzA8d8R6MF8YMIx8uk47hDSJbj14IPzOGc7jPLvwTGg5uAYDbe2tt56cLtznvEnS6yDqCcEaWi91DvrbLJZz7b1aFtz1aO+2OZWvn+/+4CHeB6BMYaqBLfjPNRY6RFT2JJYby+uAk4WUTrtlmJ4hgPYb2q1XGDQjaK8pgJHvqNaAX+KyuIkDXpgQinb46nOulnn4b5laUHTxLfseeArAoNOeJlOIjdoal0n1FA7tKFv5roK+YaHOqP3P0XyKHPHY+MhTRe5uCZnKhtJKw2eSrSoBDPLtpZuNcFNJcFyiCMxOaaHIfXz1e8HQbWLySrBQ4x0x1qlhnHlnz2HQEC6TNb0gTHXa7IKhcaHqkE015hk9whA0YeWiLIXf7Fa2CZo3DjqjB4tTuF8jIcbfcEx5z/w4sXpQhXW+ju0cqh7icTFmRMaG+v6CIvTjcSpHcH8JEsF3EPh3fRthYdVLLgI2fWXm85/pGFE4l046s70L+yKCcirGFR+jbpy3kMmiCGHrSezVONsn1RBixncyk2PcVWk7DlgxHo8iZwDyq5uAUD854dZhdIFYzKoQig2haUKi1lVufz2RZUZPZ41n/hrOQB6h0Hhg8I367FNoEHgeM/KY7szSeQwD8q2WE3HM35ZLl0K1MJiOtHIkBclRQUwZnyOWcNsRQQgVLj1PSqkjF9DsoOSaSg3iinKzvfmgsNFFfpP/2T3GLGvL4fHEfwIX1sVvXcPqLztehWGcfn9nI2U9nTfCgJPe/jFPLZwgVEzimBgAm0VIyK2tt1cE/AzQdLK+SxLSQ4aDCZnnId94OG2S1XwvnTbNk/ZnhyRCQT+sZM6z9g6LXL1BOBe+zJySiFkHAINCtnQokbCJ/apCv0foqPiZVfhpywAAAAASUVORK5CYII="},"746f":function(t,e,n){var o=n("428f"),i=n("1a2d"),r=n("e538"),s=n("9bf2").f;t.exports=function(t){var e=o.Symbol||(o.Symbol={});i(e,t)||s(e,t,{value:r.f(t)})}},7715:function(t,e,n){},"7abd":function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXm9PXq+Pno9vfs+vttWKBGAAACPElEQVQozw3RQWrbQACF4TfCMjPqZgIj4RRaxsZKE0PuMBZ2cLKaCI9RDAXFmJJknUWWI1O1UlamOMHJSjGkuFn3AD2Cr9CepDrAg+/xIxK4QwIqHHQkUhQ/WuphInVIFBojl8QXc012Tgq4RTtVHWVLZVFh1tEoI91uiN4joCqde8Ukn/zGM1B2W4ari2PtTwyw55Ld+Wways54qhGPyS6FzbIT3lIY8WwWdCq56Yolx6KmSKzoqrsCB5heAp4TGNQWJ1Pc6XlE5jQD5OlIX9I47A9uiUQcPQxcury/ToyxWJG/za6ki88crxKPocKS59Sl3EtBG7C89fCGflpfqoSzCeC4crioJA7F0V5+8MaSIk4qSCdwzpogmbqzEirVpGiS2dOVJvUuuqFEmhHao06KEpq+8lvHI14NJk3Qrmi9vBuRLwAz0qZB4hsDXQFXgtnlpDX3C6ug9BquSw/CYtwAzuTz5vuQNdr/YibhR68378ehZH30FSpjh71LpQkrsj+Q062h5WwZ5wlRoD6uQJy1DqvSYuCUapMBqT5YA4ZFw4KlWapxoUGlKWrx0eDQvmigu4WMYt97ruru98fYL8/0lG6CTOFcFWBhFK5gKw19h2JN808nh7xhkU6sWKLXdtkqBL6h+lULK5k19wFB/FldnGYf3LDeuf6IC2/MzJOSOP0qPxLqzaGIqtBcFIItrstkazONOkrc1D1czjuwEGESB4JJnjgSMN7PXAu7fZQpl1C236C+9mM4Af8P98Ch4R2TRl8AAAAASUVORK5CYII="},"802e":function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEUWGBkYGhsdHyAfISI1t/v6AAAB5ElEQVQozxXQsYoTURSA4f/EeycZsDgDdySDjihk38Hy3GWi2J2BCaziQhaiaB+tt9AFu1kwvYUPsIXNPoB9BAUfwAfwEUzKv/v4odGrroyp9/rUaC6rZ5skv5F8qPsfYYP+yKUMymmAEEeW55oUR4o8jr05KNzJ07yvB7w0KKfLwcQUSjfmMU0PJfPHFoEVU+ohNrcKMEzMQ23FDnVSI2dqtYWI7KlLu6vE4UnyvKc3SJuL7lBbeEEl42ItpGLjzIT8PRJCmkRjVpVpsbJFVN0687okJNZiHAr5Z7MV0BnGIDc+THM1zlbieBc1Fq+tH5BH+OpnbWkj40hSqC8Lw2TvFuF0SUFJCk2IytXbjeqcRAt6NHpnrUkUU4KRzZs8RCK8N/Akn2W04LwxMU/V7XK0bDyN2RxfDyx7I4h5vjZby72V8UnOWumZL3qtYc+8DTE0siSBMXGhywx2dMYPnQHbxdFZ7deiNGxCCtD/QWnbwDoGhRYPDzUdUA3krjpnkvdAgDN4ddLkEQSov9qjd42HaDjI34gEqS9TUueAk+sc4qg5ws407KQYKs8G1jv4xBlqBVk6cb4dISZIwVi1Jzu4+HLk6lyfUxkXvwy+1Q+4WVdHIhwfybZ6CWVhxMEhShOgsP/HOW0MvZJeFwAAAABJRU5ErkJggg=="},"82da":function(t,e,n){},"897d":function(t,e,n){(function(e,n){t.exports=n()})(window,(function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var i=e[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=9)}([function(t,e,n){var o=n(7);"string"===typeof o&&(o=[[t.i,o,""]]),o.locals&&(t.exports=o.locals);var i=n(10).default;i("56ca1821",o,!1,{})},function(t,e,n){var o=n(3),i=n(4),r=n(5);function s(t,e){return o(t)||i(t,e)||r()}t.exports=s},function(t,e){function n(t){return n="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function o(e){return"function"===typeof Symbol&&"symbol"===n(Symbol.iterator)?t.exports=o=function(t){return n(t)}:t.exports=o=function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":n(t)},o(e)}t.exports=o},function(t,e){function n(t){if(Array.isArray(t))return t}t.exports=n},function(t,e){function n(t,e){var n=[],o=!0,i=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(o=(s=a.next()).done);o=!0)if(n.push(s.value),e&&n.length===e)break}catch(c){i=!0,r=c}finally{try{o||null==a["return"]||a["return"]()}finally{if(i)throw r}}return n}t.exports=n},function(t,e){function n(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}t.exports=n},function(t,e,n){"use strict";var o=n(0),i=n.n(o);i.a},function(t,e,n){e=t.exports=n(8)(!1),e.push([t.i,".vue-pull-to-wrapper[data-v-81faaf1a],\n.vue-pull-to-wrapper > .scroll-container[data-v-81faaf1a] {\n padding: 0;\n border: 0 none;\n margin: 0;\n}\n.vue-pull-to-wrapper[data-v-81faaf1a] {\n display: -webkit-box;\n display: -webkit-flex;\n display: flex;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -webkit-flex-direction: column;\n flex-direction: column;\n height: 100%;\n}\n.vue-pull-to-wrapper > .scroll-container[data-v-81faaf1a] {\n -webkit-box-flex: 1;\n -webkit-flex: 1;\n flex: 1;\n overflow-x: hidden;\n overflow-y: scroll;\n -webkit-overflow-scrolling: touch;\n}\n.vue-pull-to-wrapper > .scroll-container > .bottom-filler[data-v-81faaf1a] {\n height: 0px;\n}\n.vue-pull-to-wrapper > .action-block[data-v-81faaf1a] {\n position: relative;\n width: 100%;\n}\n.vue-pull-to-wrapper > .action-block > .default-text[data-v-81faaf1a] {\n height: 100%;\n line-height: 50px;\n text-align: center;\n}\n.vue-pull-to-wrapper[data-v-81faaf1a],\n.vue-pull-to-wrapper > .action-block-bottom[data-v-81faaf1a],\n.vue-pull-to-wrapper > .scroll-container > .bottom-fill[data-v-81faaf1a] {\n -webkit-transition-timing-function: cubic-bezier(0, 0, 0, 1);\n transition-timing-function: cubic-bezier(0, 0, 0, 1);\n}\n",""])},function(t,e,n){"use strict";function o(t,e){var n=t[1]||"",o=t[3];if(!o)return n;if(e&&"function"===typeof btoa){var r=i(o),s=o.sources.map((function(t){return"/*# sourceURL="+o.sourceRoot+t+" */"}));return[n].concat(s).concat([r]).join("\n")}return[n].join("\n")}function i(t){var e=btoa(unescape(encodeURIComponent(JSON.stringify(t)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,"+e;return"/*# "+n+" */"}t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var n=o(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n})).join("")},e.i=function(t,n){"string"===typeof t&&(t=[[null,t,""]]);for(var o={},i=0;i2&&void 0!==arguments[2]?arguments[2]:0;if(null==e)return t;var o,i="object"===("undefined"===typeof performance?"undefined":c()(performance))?performance:Date,r=null;return function(){var s=i.now();if(null!=r&&clearTimeout(r),o||(o=s),0!==n&&s-o>=n)t.apply(this,arguments),o=s;else{var a=this,c=Array.prototype.slice.call(arguments);r=setTimeout((function(){return r=null,t.apply(a,c)}),e)}}}var u=function(){var t=!1;try{window.addEventListener("test",e,{get passive(){return t=!0,!0}}),window.removeEventListener("test",e)}catch(n){t=!1}return t&&{passive:!0};function e(){}}();function f(t,e){var n=Object.create(t);return Object.assign(n,e),n}var d={pullText:"下拉刷新",triggerText:"释放更新",loadingText:"加载中...",doneText:"加载完成",failText:"加载失败",loadedStayTime:400,stayDistance:50,triggerDistance:70},h={pullText:"上拉加载",triggerText:"释放更新",loadingText:"加载中...",doneText:"加载完成",failText:"加载失败",loadedStayTime:400,stayDistance:50,triggerDistance:70},p="loaded-";function g(t,e,n,o){t.setProperty("transition-property",e||""),t.setProperty("transition-duration",n||""),t.setProperty("transition-delay",o||"")}function A(t){return"string"===typeof t&&t.startsWith(p)}function m(t,e){switch(e){case"pull":return t.pullText;case"trigger":return t.triggerText;case"loading":return t.loadingText;case"loaded-done":return t.doneText;default:return A(e)?t.failText:""}}var v={name:"vue-pull-to",props:{distanceIndex:{type:Number,default:2},topBlockHeight:{type:Number,default:50},bottomBlockHeight:{type:Number,default:50},wrapperHeight:{type:String,default:"100%"},topLoadMethod:Function,bottomLoadMethod:Function,isThrottleTopPull:{type:Boolean,default:!0},isThrottleBottomPull:{type:Boolean,default:!0},isThrottleScroll:{type:Boolean,default:!0},isTouchSensitive:{type:Boolean,default:!0},isScrollSensitive:{type:Boolean,default:!0},isTopBounce:{type:Boolean,default:!0},isBottomBounce:{type:Boolean,default:!0},isBottomKeepScroll:Boolean,topConfig:Object,bottomConfig:Object},data:function(){return{startY:null,startX:null,distance:0,diff:0,beforeDiff:0,state:"",shouldPullDown:!1,shouldPullUp:!1,shouldPassThroughEvent:!1,throttleEmitTopPull:null,throttleEmitBottomPull:null,throttleEmitScroll:null,throttleOnInfiniteScroll:null}},computed:{_topConfig:function(){return f(d,this.topConfig)},_bottomConfig:function(){return f(h,this.bottomConfig)},direction:{cache:!1,get:function(){var t=this.distance;return t>0?"down":t<0?"up":0}},topText:function(){return this.distance>0?m(this._topConfig,this.state):""},bottomText:function(){return this.distance<0?m(this._bottomConfig,this.state):""}},watch:{state:function(t){var e=this,n=this.distance,o=n>0?"top-state-change":"bottom-state-change";if(this.$emit(o,t),"string"!==typeof t||""===t);else if("loading"===t){var i=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"done",o=p+n;e.state=o,t=null};if(n>0?this.topLoadMethod(i):this.bottomLoadMethod(i),null===t)return;n>0?this.scrollTo(this._topConfig.stayDistance):this.scrollTo(-this._bottomConfig.stayDistance)}else if(A(t)&&null==this.startY){var r=n>0?this._topConfig:this._bottomConfig,s=this.$refs["bottom-filler"];if(s&&!(n>0)){var a=this.$refs["action-block-bottom"],c=this.diff;if(null!=a&&c<0){this.scrollTo(0,0);var l=a.style;l.setProperty("transform","translate(0, ".concat(c,"px)"));var u=s.style;u.setProperty("height","".concat(-c,"px")),this.$refs["scroll-container"].scrollTop-=c;var f="200ms",d="".concat(r.loadedStayTime,"ms");return g(l,"transform",f,d),g(u,"height",f,d),l.setProperty("transform","translate(0, 0)"),void u.setProperty("height","0px")}}this.scrollTo(0,200,r.loadedStayTime)}},isTouchSensitive:"updateTouchSensitivity",isScrollSensitive:"updateScrollSensitivity"},methods:{scrollTo:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:200,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;this.diff=t;var o=this.$refs["action-block-bottom"];if(null!=o){var i=o.style;i.getPropertyValue("transform")&&(g(i,"none"),i.setProperty("transform",""))}var r=this.$refs["bottom-filler"];if(null!=r){var s=r.style;s.getPropertyValue("height")&&(g(s,"none"),s.setProperty("height",""))}var a=this.$el.style;g(a,e>0||n>0?"transform":"none","".concat(e,"ms"),"".concat(n,"ms")),a.setProperty("transform","translate(0, ".concat(t,"px)"))},checkBottomReached:function(){var t=this.$refs["scroll-container"];return t.scrollTop+t.offsetHeight+1>=t.scrollHeight},handleTouchStart:function(t){var e=s()(t.touches,1),n=e[0];this.startY=n.clientY,this.startX=n.clientX,this.beforeDiff=this.diff;var o=this.$refs["scroll-container"];this.shouldPullDown=this.isTopBounce&&0===o.scrollTop,this.shouldPullUp=this.isBottomBounce&&this.checkBottomReached(),this.shouldPassThroughEvent=!1},handleTouchMove:function(t){var e=s()(t.touches,1),n=e[0],o=n.clientY,i=n.clientX,r=this.startY,a=this.startX,c=(o-r)/this.distanceIndex+this.beforeDiff,l=this.state;"loading"!==l||c*this.distance>0||(c=c<0?3e-308:-3e-308),this.distance=c;var u=this.shouldPassThroughEvent;if(Math.abs(o-r)0?this.shouldPullDown:this.shouldPullUp){var f;if(u||(t.preventDefault(),t.stopPropagation()),this.scrollTo(c,0),c>0){if(this.isThrottleTopPull?this.throttleEmitTopPull(this.diff):this.$emit("top-pull",this.diff),"function"!==typeof this.topLoadMethod)return;f=this._topConfig}else{if(this.isThrottleBottomPull?this.throttleEmitBottomPull(this.diff):this.$emit("bottom-pull",this.diff),"function"!==typeof this.bottomLoadMethod)return;f=this._bottomConfig}var d=Math.abs(c)1&&void 0!==arguments[1]?arguments[1]:0,o=arguments.length>2?arguments[2]:void 0;return l(t.$emit.bind(t,o),e,n)};this.throttleEmitTopPull=e(200,300,"top-pull"),this.throttleEmitBottomPull=e(200,300,"bottom-pull"),this.throttleEmitScroll=e(100,150,"scroll"),this.throttleOnInfiniteScroll=l((function(){t.checkBottomReached()&&t.$emit("infinite-scroll")}),400)},init:function(){this.createThrottleMethods(),this.bindEvents()}},mounted:function(){this.init()}},b=v;n(6);function y(t,e,n,o,i,r,s,a){var c,l="function"===typeof t?t.options:t;if(e&&(l.render=e,l.staticRenderFns=n,l._compiled=!0),o&&(l.functional=!0),r&&(l._scopeId="data-v-"+r),s?(c=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),i&&i.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(s)},l._ssrRegister=c):i&&(c=a?function(){i.call(this,this.$root.$options.shadowRoot)}:i),c)if(l.functional){l._injectStyles=c;var u=l.render;l.render=function(t,e){return c.call(e),u(t,e)}}else{var f=l.beforeCreate;l.beforeCreate=f?[].concat(f,c):[c]}return{exports:t,options:l}}var C=y(b,o,i,!1,null,"81faaf1a",null);C.options.__file="src/vue-pull-to.vue";var x=C.exports;e["default"]=x},function(t,e,n){"use strict";function o(t,e){for(var n=[],o={},i=0;in.parts.length&&(o.parts.length=n.parts.length)}else{var s=[];for(i=0;i0&&(!S.multiline||S.multiline&&"\n"!==A(w,S.lastIndex-1))&&(D="(?: "+D+")",P=" "+P,U++),n=new RegExp("^(?:"+D+")",T)),x&&(n=new RegExp("^"+D+"$(?!\\s)",T)),y&&(i=S.lastIndex),a=o(p,k?n:S,P),k?a?(a.input=b(a.input,U),a[0]=b(a[0],U),a.index=S.lastIndex,S.lastIndex+=a[0].length):S.lastIndex=0:y&&a&&(S.lastIndex=S.global?a.index+a[0].length:i),x&&a&&a.length>1&&o(h,a[0],n,(function(){for(c=1;cB;B++)if((h||B in C)&&(v=C[B],b=x(v,B,y),t))if(e)I[B]=b;else if(b)switch(t){case 3:return!0;case 5:return v;case 6:return B;case 2:l(I,v)}else switch(t){case 4:return!1;case 7:l(I,v)}return f?-1:i||u?u:I}};t.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6),filterReject:u(7)}},c0aa:function(t,e,n){"use strict";n("1b41")},cf68:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyBAMAAADsEZWCAAAAD1BMVEXm5ubo6Ojp6enr6+vt7e1FnZagAAACrklEQVQ4yx1SixUbMQgT3AKAFwDcAfzpBN1/qMrJS5w7bCQhC6IGSUGYQJd6Ox9ZPXi1AGJBavhUTT0JjYPGAab9WcDYIxsmlnxkayX8mhxCmKHA75az5cfRbWybEExiu08xDSgGym0mwuf3j4SvHeQxDJJzh2zp4iOlrD8iOb4SXyC1wiOLRTcnrje+nGamFeXVKWkmzbFIPChkmJ6Fg7mBpV8n+JGOVCd4jv1thThkjeQGNeafpeV3rsEWLfyWc8tC9jOv6FQ8rRzHOOVB+jCYEUAJpDvh8xHNFm/Tm5p5lw94Pp3NhtKEfQsGvnXhowdZE73hPwxKvjDd4i4PCdd0fe3W5fO8ktAsUAacLgstpUw60JCiPLg2XpkgiqPIYYXJd9ksGIT3q+LlevypzItvO+s0F1dBzVr2QDMUkYmuyGcrIS44mVJ7JVKwQXjYuBYp0Uetecbswzsikzu3gUR8bJC/C8Gd/NAzI/xdUGOYQQHDZ8X2d5XuzGRUiXAi9si5CRgoiToRZPtzLJkd0FUHRHZwJf0BHT1sE7gcnh0jmKKlSSF4/GBirGk5+K9NKlGDCfc9JtPhg78JdabH0YQRKNZnJ8tFnPfXHJb4xum1TTCeEmyEdbyEJLjznMLHuFD2Y9NEkSleIBs7SiCbblhgctVi9ch++kDYnn1C9DA5TvdPsToXM55wI6k+8eKT1blwPTqWb5CFJ+7dTBmab+KHy+xwNtItXhZNSpHD2fxnynrxG3ZBKRe8KBpXk11AnadlccEhr9w1nBBvBylNkv7A8eqpGBCDqhitmWQXBjjdS6idr/QjXWLDeMzMbVDoJuM8zN7WenMZWXgZ2vX3F01J3jHZbwk1LRP+DWEvDJtOUoh/AIaBUz5VpWyhuyx4QtgL/NmgC6kM/JvNe+R/C/5aL7BKIbYAAAAASUVORK5CYII="},d0e3:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEXh7eHl8eXj7+Pn8+eTbH1KAAACPElEQVQozxWPQWrbQABF/0xn3JFKQRTZOIuUsbCCbOgdRoYEOauxkYPcTRyTlPQWIxEltrsRwQ6hK9nEQek6F+gNTE/Q3qLLusv34cN7SH3mFicdYW4gNIhJWXPBRVXzjcFD0IqeU4o4PRbAIVjyico0vJpIifqPfL80QN9DAQY5ucRHE/hpHxBldXe9GilaHKcKMlj6pho2zXgkNdBl0oJ8kiF1DSiJF1ZHBJkQr0Dbux/5I42Zp4cFahJDFGeW6/QjBwmFY/Q7vZ2SnoOdW2parv/Cnm81+m0xrEfiVXQ3W4nOXIqVYi3l6AAQBwMFkViVBANMto4enXHPNTkHBB0oVj4r5vHzCWayrgBvxtygDlDB2CNDjd80ZInY69aKVYZcfJ8DW+fWuc+syEODALx+ojqoafHsthTI+ZW27PGpIeo/cR6YKcbqIuIFhHmBrzAovzIOOJk1ucvcDzrMRYGVBH2yvcAOf0KiKwfRovBI3tm/kW1eemtfNWwIIXE2mJNhvoszfmMBfRCv0OPwd2321uDW3nx2q/BDxFVeoN1g7a6Im8yRnoawa8kbdXnU0cHeTMxKfZGlJgvLb3sKsxgglQnDdAfvj9LUnqWRDo0GiUmPwyU7TAsD7wHeIW3Nfy1qVGKoE9NgJCdYCAexNRob9yCn4DAQmXtQuUtera6bEmTTXhZy6h856xi4mnEl6BI9mfISkLbtJyZIMJIAUd5ZOBEu88KRAk71yxfItj/hpIB0Errv4gO1os4/UICf+o3kkqwAAAAASUVORK5CYII="},d28b:function(t,e,n){var o=n("746f");o("iterator")},d784:function(t,e,n){"use strict";n("ac1f");var o=n("e330"),i=n("6eeb"),r=n("9263"),s=n("d039"),a=n("b622"),c=n("9112"),l=a("species"),u=RegExp.prototype;t.exports=function(t,e,n,f){var d=a(t),h=!s((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),p=h&&!s((function(){var e=!1,n=/a/;return"split"===t&&(n={},n.constructor={},n.constructor[l]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return e=!0,null},n[d](""),!e}));if(!h||!p||n){var g=o(/./[d]),A=e(d,""[t],(function(t,e,n,i,s){var a=o(t),c=e.exec;return c===r||c===u.exec?h&&!s?{done:!0,value:g(e,n,i)}:{done:!0,value:a(n,e,i)}:{done:!1}}));i(String.prototype,t,A[0]),i(u,d,A[1])}f&&c(u[d],"sham",!0)}},d81d:function(t,e,n){"use strict";var o=n("23e7"),i=n("b727").map,r=n("1dde"),s=r("map");o({target:"Array",proto:!0,forced:!s},{map:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}})},df5e:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAATlBMVEXdzaHh0KPgz6LdzKDezqLczJ7ezZ/fz6Dcy5zi0aXdzZ3fz6Tfz57h0KDg0aLcyZrg0KXi0qPfzZ3j06bh0qbdyJbfzJrhz5/cxpLZwo0vDconAAAFn0lEQVRIxxyPW5LjMAwDAT5FybLl2JnM3P+i6+wXWVC1GoQGaD0h4XM3Q5o4T0HgABHBi6pZ4CDXXcUOFd6VhqC3Kch4EI8w9oMXwvU6m5LOOvcxKMOhuu8i5+5cMjcgb0t4F2uvOoeI3/MlT4IqsbtM9UG2AGSXUOsxzPevnXzK1CSHytZLvx7VdQmUcJsJCxJh2nmHW12Qod1qPjt8pih47uQ9aGpoNWF+yElCt60oH7vdIU/MnlRPSBLC/VwqxcKR8PFqnADN9ih5ufqnTlG9KwCofvs7kKYqOPHTNMQ93j9qNImFw9vjHPZ0F1m8hUUVB/Q/TrRYDMXr9++APMFARAt6sPh6wVAXzxUGhZsFUwCNfPZ8/72TAHebAhvuOuT3gO1Vn5d9Jd5sBRkg0p2seL9B7ulkjFJFIt9HPpLzdSzzMP3UcodAfMqC6pBuET2heHK1itZf1GZ1bi0BwOSxiCS8f/JBHMPMM4XCu3Mt1uz9lJbDJRqsKDZuikzkvskQEz6hanfDfO494azY5JpqPqOF1RhxD9XYEdaNxiqWqakKgmPfmrsta8KAiwF4HBxGVUJAgeSqQaiRRZJ7D2jedhw5t1CIAKxag0CBA60BpoBE6DcUi8O5AuM4pLfN0kHLmeu2B4e6HofqbgxsTWUw3PAODqa1oDtyzgXBlusi1KFdclMPE8O3jvLJ8RNi5/RxDQVzVmXA233XQ4KummunfxvLOZo+iH37964YjP06995CTdu9hsvErqJNzmf4wTrZ5DL7+qW9EoLnadrx67b8dUtrJnBXaT1N1uvPaYRKpWkq52xNsMN7vv4Sdryt/f4MhQoMCKnvVxikai1CQ6ZsnwJDc8+3Y/z8HcfvYQNq66pnAu1Hwa+3KNSwbNu8h3nDPqTl9fl7tx8fBhFfdS0o0F3JUKEZtZG9b/LZEM95lzaR30OnWPzroMxyZYdBIMoMnpN0J+m7/40+/P4soFSUjgzE7yY5zrMJuoZv0CmpVguYx1pprfb5HOviRVhHUVi/352shxCYrYBZxGtVaxiAz/MsaGSIsB7R1t4zJXH//n7RTTQQwxqcGEqEvklFHUgiO2GvJV+jAIPR+N29usWDoiSOVrN3XuqT1egQJAAU9EwslVJC8u0rGcy+WPqktJhjfMpatIG6CDAb0v5H34MGKqiVRue7GGLZ9Otxtt4JIrAhxBDwDuqI9JavcO0A7GlqFt219tH/bln9jBXzaKWAEqJV0CBxs5TwM8EvUPHaa8S86vN303MVWOsl3goDBHPWSoQ9c0kQmCKljfsKNH1+ofEOHW8a9a7glZGS8fPieL/SRSs0LAhI4FDTnXs1QYtubv2+IXPZpHB4bhivRexBkYKsSrYXNjvMUbVXpVJ+N6haV72c1k2zrnv5IYBMJBYTSZx0KTkoM3vY93rU/qs7zHplc/3d2ACadhFWByrn9LUk2IWb5JywvawTQc3F0iz+lgsBmInAIemBJtft2plKIlAFOgcroigrG2XlDsAzywQECNyaI8yr2ogoh7D4qJOYmZBzQgoZAM1PAcB8sDrr1uE5CDMR+nWSSVUGUCHAs8Vd21HOE0FzNj37pX0sLp9p3K8k++xxpkmzDxK64rmTSJnDUuIgTeslui6lg92jonZXI4jqNiUuzN4IagcKMjCniMGCODoo8T4tGDprn2hRww+NrnYiCwokd9iiWrkmbRfXYGLAoZrjO1lVQKExjUy5fIkgJURmz2uGFdASwwlWx5gDVTMK7hP6ISRVsFbYNmqtZL9MQtio285PaekyzDhZmtdexCYB0SZcTmBdhvdbmAEonk8hwcHQuZN1kVqrhyKoHHsnQhQAjF7SG533Da2S4LGjx1LoZqp7XeKQLDUBmYmydG0NQHpMeR5lRIRQc1PQ2ASMQflF4YBDMt0/GFlEHeRwCcEAAAAASUVORK5CYII="},e01a:function(t,e,n){"use strict";var o=n("23e7"),i=n("83ab"),r=n("da84"),s=n("e330"),a=n("1a2d"),c=n("1626"),l=n("3a9b"),u=n("577e"),f=n("9bf2").f,d=n("e893"),h=r.Symbol,p=h&&h.prototype;if(i&&c(h)&&(!("description"in p)||void 0!==h().description)){var g={},A=function(){var t=arguments.length<1||void 0===arguments[0]?void 0:u(arguments[0]),e=l(p,this)?new h(t):void 0===t?h():h(t);return""===t&&(g[e]=!0),e};d(A,h),A.prototype=p,p.constructor=A;var m="Symbol(test)"==String(h("test")),v=s(p.toString),b=s(p.valueOf),y=/^Symbol\((.*)\)[^)]+$/,C=s("".replace),x=s("".slice);f(p,"description",{configurable:!0,get:function(){var t=b(this),e=v(t);if(a(g,t))return"";var n=m?x(e,7,-1):C(e,y,"$1");return""===n?void 0:n}}),o({global:!0,forced:!0},{Symbol:A})}},e160:function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAADFBMVEX6+fP8+/X+/ff///kbczPAAAACeElEQVQozxXHQUgUUQAG4P8936yzs6VvZNZmN9QxVxiF9OLBoOjtOC6rQq6ygXjI2fCQBdXBg4egtzFGdqkoI+zgBFbqkm3hQSxhFYLotOcubeKhOnVYoqQy+m4f5g5TvpX0xHLbLY9j8SMhJp+Jk4LfAUS2kVRIjILmnwGBTX42PhCVlDJQkIiy2nWAvaJ1h+oFIpJ0hMSYVbyyrgDWshcMpMyL1brPDQKWmduO+KTJ6XeXAMK9Yc3FpD7atyNwg6kt5XgFpLPhjUTFSYVn2abDiugGShwD8JTVRJVo/2ecuKtRb/qc4BK+9TboFfokog4T2Fn6Oqdnsjk90NMS76Rji6E0NmwkPBAZ4Xbkw8KoDAkAbEhkc78e9omxxgxg6qa5HvMv+UZbCV0qmHnSHKl5TxeA2XTCGWekR581mwC5crBH81PznASqB9va3TbkYAjJPLfg5uBfXaJgIgIBv9eessRIhxe7PA7kj6uUMeMaQ/OEQOYRaaHlqH2Gxwsl6E/pwVY5FH7uCypBZPKvDQyVziYBrAkMURe2MOOOxG/eQpp5PF+bFzUV5HtPj9GeiVSNZDELleifYTp9NAjsoiXg4cW+4ZORkdSMB/B74aAdjhsVakhgkugsbmqcDSLEoWp8zRjrux3tli6Q5uM3E+maT99Wy0RiP7tboiuRZle2c6CYeL2kcUc1KvPtQKucogMadKVTQOJYCeyCYlhQQ/Q7Etfd/vBygy9iqy+LyHeF46saCYvW6ingsbA9RBWtdi8GgUXW+oQx9/wP6bAAX1TWeV+CbShZDlQ9xT6SoSxZmKRAkmXb60kzEzkRF+Ccb94BGspGJoN/UzmyR4wjXHAAAAAASUVORK5CYII="},e3cf:function(t,e,n){"use strict";n("04aa")},e538:function(t,e,n){var o=n("b622");e.f=o},e9c4:function(t,e,n){var o=n("23e7"),i=n("da84"),r=n("d066"),s=n("2ba4"),a=n("e330"),c=n("d039"),l=i.Array,u=r("JSON","stringify"),f=a(/./.exec),d=a("".charAt),h=a("".charCodeAt),p=a("".replace),g=a(1..toString),A=/[\uD800-\uDFFF]/g,m=/^[\uD800-\uDBFF]$/,v=/^[\uDC00-\uDFFF]$/,b=function(t,e,n){var o=d(n,e-1),i=d(n,e+1);return f(m,t)&&!f(v,i)||f(v,t)&&!f(m,o)?"\\u"+g(h(t,0),16):t},y=c((function(){return'"\\udf06\\ud834"'!==u("\udf06\ud834")||'"\\udead"'!==u("\udead")}));u&&o({target:"JSON",stat:!0,forced:y},{stringify:function(t,e,n){for(var o=0,i=arguments.length,r=l(i);o ChineseUtils.t2s("初始化") diff --git a/app/src/main/java/io/legado/app/api/controller/BookSourceController.kt b/app/src/main/java/io/legado/app/api/controller/BookSourceController.kt index f5c6d007e..d4c1eb14f 100644 --- a/app/src/main/java/io/legado/app/api/controller/BookSourceController.kt +++ b/app/src/main/java/io/legado/app/api/controller/BookSourceController.kt @@ -7,7 +7,6 @@ import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonArray -import io.legado.app.utils.msg object BookSourceController { @@ -23,20 +22,16 @@ object BookSourceController { fun saveSource(postData: String?): ReturnData { val returnData = ReturnData() postData ?: return returnData.setErrorMsg("数据不能为空") - kotlin.runCatching { - val bookSource = BookSource.fromJson(postData) - if (bookSource != null) { - if (TextUtils.isEmpty(bookSource.bookSourceName) || TextUtils.isEmpty(bookSource.bookSourceUrl)) { - returnData.setErrorMsg("源名称和URL不能为空") - } else { - appDb.bookSourceDao.insert(bookSource) - returnData.setData("") - } + val bookSource = BookSource.fromJson(postData).getOrNull() + if (bookSource != null) { + if (TextUtils.isEmpty(bookSource.bookSourceName) || TextUtils.isEmpty(bookSource.bookSourceUrl)) { + returnData.setErrorMsg("源名称和URL不能为空") } else { - returnData.setErrorMsg("转换源失败") + appDb.bookSourceDao.insert(bookSource) + returnData.setData("") } - }.onFailure { - returnData.setErrorMsg(it.msg) + } else { + returnData.setErrorMsg("转换源失败") } return returnData } @@ -44,19 +39,18 @@ object BookSourceController { fun saveSources(postData: String?): ReturnData { postData ?: return ReturnData().setErrorMsg("数据为空") val okSources = arrayListOf() - val bookSources = BookSource.fromJsonArray(postData) - if (bookSources.isNotEmpty()) { - bookSources.forEach { bookSource -> - if (bookSource.bookSourceName.isNotBlank() - && bookSource.bookSourceUrl.isNotBlank() - ) { - appDb.bookSourceDao.insert(bookSource) - okSources.add(bookSource) - } - } - } else { + val bookSources = BookSource.fromJsonArray(postData).getOrNull() + if (bookSources.isNullOrEmpty()) { return ReturnData().setErrorMsg("转换源失败") } + bookSources.forEach { bookSource -> + if (bookSource.bookSourceName.isNotBlank() + && bookSource.bookSourceUrl.isNotBlank() + ) { + appDb.bookSourceDao.insert(bookSource) + okSources.add(bookSource) + } + } return ReturnData().setData(okSources) } diff --git a/app/src/main/java/io/legado/app/api/controller/RssSourceController.kt b/app/src/main/java/io/legado/app/api/controller/RssSourceController.kt index 95d80abe0..6df9c5b28 100644 --- a/app/src/main/java/io/legado/app/api/controller/RssSourceController.kt +++ b/app/src/main/java/io/legado/app/api/controller/RssSourceController.kt @@ -5,7 +5,6 @@ import android.text.TextUtils import io.legado.app.api.ReturnData import io.legado.app.data.appDb import io.legado.app.data.entities.RssSource -import io.legado.app.utils.msg object RssSourceController { @@ -21,20 +20,15 @@ object RssSourceController { fun saveSource(postData: String?): ReturnData { val returnData = ReturnData() postData ?: return returnData.setErrorMsg("数据不能为空") - kotlin.runCatching { - val source = RssSource.fromJson(postData) - if (source != null) { - if (TextUtils.isEmpty(source.sourceName) || TextUtils.isEmpty(source.sourceUrl)) { - returnData.setErrorMsg("源名称和URL不能为空") - } else { - appDb.rssSourceDao.insert(source) - returnData.setData("") - } + RssSource.fromJson(postData).onFailure { + returnData.setErrorMsg("转换源失败${it.localizedMessage}") + }.onSuccess { source -> + if (TextUtils.isEmpty(source.sourceName) || TextUtils.isEmpty(source.sourceUrl)) { + returnData.setErrorMsg("源名称和URL不能为空") } else { - returnData.setErrorMsg("转换源失败") + appDb.rssSourceDao.insert(source) + returnData.setData("") } - }.onFailure { - returnData.setErrorMsg(it.msg) } return returnData } @@ -42,18 +36,17 @@ object RssSourceController { fun saveSources(postData: String?): ReturnData { postData ?: return ReturnData().setErrorMsg("数据不能为空") val okSources = arrayListOf() - val source = RssSource.fromJsonArray(postData) - if (source.isNotEmpty()) { - for (rssSource in source) { - if (rssSource.sourceName.isBlank() || rssSource.sourceUrl.isBlank()) { - continue - } - appDb.rssSourceDao.insert(rssSource) - okSources.add(rssSource) - } - } else { + val source = RssSource.fromJsonArray(postData).getOrNull() + if (source.isNullOrEmpty()) { return ReturnData().setErrorMsg("转换源失败") } + for (rssSource in source) { + if (rssSource.sourceName.isBlank() || rssSource.sourceUrl.isBlank()) { + continue + } + appDb.rssSourceDao.insert(rssSource) + okSources.add(rssSource) + } return ReturnData().setData(okSources) } @@ -70,11 +63,11 @@ object RssSourceController { fun deleteSources(postData: String?): ReturnData { postData ?: return ReturnData().setErrorMsg("没有传递数据") - kotlin.runCatching { - RssSource.fromJsonArray(postData).let { - it.forEach { source -> - appDb.rssSourceDao.delete(source) - } + RssSource.fromJsonArray(postData).onFailure { + return ReturnData().setErrorMsg("格式不对") + }.onSuccess { + it.forEach { source -> + appDb.rssSourceDao.delete(source) } } return ReturnData().setData("已执行"/*okSources*/) diff --git a/app/src/main/java/io/legado/app/constant/AppPattern.kt b/app/src/main/java/io/legado/app/constant/AppPattern.kt index c9ed09ac0..e98f6bbf5 100644 --- a/app/src/main/java/io/legado/app/constant/AppPattern.kt +++ b/app/src/main/java/io/legado/app/constant/AppPattern.kt @@ -22,7 +22,7 @@ object AppPattern { val debugMessageSymbolRegex = Regex("[⇒◇┌└≡]") //本地书籍支持类型 - val bookFileRegex = Regex("(?i).*\\.(txt|epub|umd)") + val bookFileRegex = Regex(".*\\.(txt|epub|umd)", RegexOption.IGNORE_CASE) /** * 所有标点 diff --git a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt index f721dca47..521d79b51 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt @@ -12,15 +12,26 @@ interface BookSourceDao { @Query( """select * from book_sources - where bookSourceName like :searchKey - or bookSourceGroup like :searchKey - or bookSourceUrl like :searchKey - or bookSourceComment like :searchKey + where bookSourceName like '%' || :searchKey || '%' + or bookSourceGroup like '%' || :searchKey || '%' + or bookSourceUrl like '%' || :searchKey || '%' + or bookSourceComment like '%' || :searchKey || '%' order by customOrder asc""" ) fun flowSearch(searchKey: String): Flow> - @Query("select * from book_sources where bookSourceGroup like :searchKey order by customOrder asc") + @Query( + """select * from book_sources + where enabled = 1 and + (bookSourceName like '%' || :searchKey || '%' + or bookSourceGroup like '%' || :searchKey || '%' + or bookSourceUrl like '%' || :searchKey || '%' + or bookSourceComment like '%' || :searchKey || '%') + order by customOrder asc""" + ) + fun flowSearchEnabled(searchKey: String): Flow> + + @Query("select * from book_sources where bookSourceGroup like '%' || :searchKey || '%' order by customOrder asc") fun flowGroupSearch(searchKey: String): Flow> @Query("select * from book_sources where enabled = 1 order by customOrder asc") @@ -39,7 +50,7 @@ interface BookSourceDao { """select * from book_sources where enabledExplore = 1 and trim(exploreUrl) <> '' - and (bookSourceGroup like :key or bookSourceName like :key) + and (bookSourceGroup like '%' || :key || '%' or bookSourceName like '%' || :key || '%') order by customOrder asc""" ) fun flowExplore(key: String): Flow> @@ -48,7 +59,7 @@ interface BookSourceDao { """select * from book_sources where enabledExplore = 1 and trim(exploreUrl) <> '' - and (bookSourceGroup like :key) + and (bookSourceGroup like '%' || :key || '%') order by customOrder asc""" ) fun flowGroupExplore(key: String): Flow> @@ -74,6 +85,9 @@ interface BookSourceDao { @Query("select * from book_sources where enabled = 1 and bookSourceGroup like '%' || :group || '%'") fun getEnabledByGroup(group: String): List + @Query("select * from book_sources where enabled = 1 and bookSourceType = :type") + fun getEnabledByType(type: Int): List + @get:Query("select * from book_sources where trim(bookUrlPattern) <> '' order by enabled desc, customOrder") val hasBookUrlPattern: List diff --git a/app/src/main/java/io/legado/app/data/dao/BookmarkDao.kt b/app/src/main/java/io/legado/app/data/dao/BookmarkDao.kt index 4fd2e82e5..02451f168 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookmarkDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookmarkDao.kt @@ -7,7 +7,11 @@ import io.legado.app.data.entities.Bookmark @Dao interface BookmarkDao { - @get:Query("select * from bookmarks") + @get:Query( + """ + select * from bookmarks order by bookName collate localized, bookAuthor collate localized, chapterIndex, chapterPos + """ + ) val all: List @Query( diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt index 4446d36eb..8a3a632d5 100644 --- a/app/src/main/java/io/legado/app/data/entities/Book.kt +++ b/app/src/main/java/io/legado/app/data/entities/Book.kt @@ -6,6 +6,8 @@ import io.legado.app.constant.AppPattern import io.legado.app.constant.BookType import io.legado.app.constant.PageAnim import io.legado.app.data.appDb +import io.legado.app.help.BookHelp +import io.legado.app.help.ContentProcessor import io.legado.app.help.config.AppConfig import io.legado.app.help.config.ReadBookConfig import io.legado.app.model.ReadBook @@ -271,7 +273,13 @@ data class Book( this.tocHtml = this@Book.tocHtml } - fun changeTo(newBook: Book) { + fun changeTo(newBook: Book, toc: List): Book { + newBook.durChapterIndex = BookHelp + .getDurChapter(durChapterIndex, durChapterTitle, toc, totalChapterNum) + newBook.durChapterTitle = toc[newBook.durChapterIndex].getDisplayTitle( + ContentProcessor.get(newBook.name, newBook.origin).getTitleReplaceRules() + ) + newBook.durChapterPos = durChapterPos newBook.group = group newBook.order = order newBook.customCoverUrl = customCoverUrl @@ -279,23 +287,11 @@ data class Book( newBook.customTag = customTag newBook.canUpdate = canUpdate newBook.readConfig = readConfig - delete(this) - appDb.bookDao.insert(newBook) - } - - fun upInfoFromOld(oldBook: Book?) { - oldBook?.let { - group = oldBook.group - durChapterIndex = oldBook.durChapterIndex - durChapterPos = oldBook.durChapterPos - durChapterTitle = oldBook.durChapterTitle - customCoverUrl = oldBook.customCoverUrl - customIntro = oldBook.customIntro - order = oldBook.order - if (coverUrl.isNullOrEmpty()) { - coverUrl = oldBook.getDisplayCover() - } + if (appDb.bookDao.has(bookUrl) == true) { + delete() + appDb.bookDao.insert(newBook) } + return newBook } fun createBookMark(): Bookmark { @@ -313,20 +309,19 @@ data class Book( } } + fun delete() { + if (ReadBook.book?.bookUrl == bookUrl) { + ReadBook.book = null + } + appDb.bookDao.delete(this) + } + companion object { const val hTag = 2L const val rubyTag = 4L const val imgStyleDefault = "DEFAULT" const val imgStyleFull = "FULL" const val imgStyleText = "TEXT" - - fun delete(book: Book?) { - book ?: return - if (ReadBook.book?.bookUrl == book.bookUrl) { - ReadBook.book = null - } - appDb.bookDao.delete(book) - } } @Parcelize diff --git a/app/src/main/java/io/legado/app/data/entities/BookSource.kt b/app/src/main/java/io/legado/app/data/entities/BookSource.kt index 226830295..fed30b16c 100644 --- a/app/src/main/java/io/legado/app/data/entities/BookSource.kt +++ b/app/src/main/java/io/legado/app/data/entities/BookSource.kt @@ -11,6 +11,7 @@ import io.legado.app.utils.* import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import splitties.init.appCtx +import java.io.InputStream @Parcelize @TypeConverters(BookSource.Converters::class) @@ -203,13 +204,17 @@ data class BookSource( companion object { - fun fromJson(json: String): BookSource? { + fun fromJson(json: String): Result { return SourceAnalyzer.jsonToBookSource(json) } - fun fromJsonArray(json: String): List { + fun fromJsonArray(json: String): Result> { return SourceAnalyzer.jsonToBookSources(json) } + + fun fromJsonArray(inputStream: InputStream): Result> { + return SourceAnalyzer.jsonToBookSources(inputStream) + } } class Converters { diff --git a/app/src/main/java/io/legado/app/data/entities/RssSource.kt b/app/src/main/java/io/legado/app/data/entities/RssSource.kt index b4fa7dfe6..32c5a2743 100644 --- a/app/src/main/java/io/legado/app/data/entities/RssSource.kt +++ b/app/src/main/java/io/legado/app/data/entities/RssSource.kt @@ -121,7 +121,7 @@ data class RssSource( @Suppress("MemberVisibilityCanBePrivate") companion object { - fun fromJsonDoc(doc: DocumentContext): RssSource? { + fun fromJsonDoc(doc: DocumentContext): Result { return kotlin.runCatching { val loginUi = doc.read("$.loginUi") RssSource( @@ -152,23 +152,25 @@ data class RssSource( loadWithBaseUrl = doc.readBool("$.loadWithBaseUrl") ?: true, customOrder = doc.readInt("$.customOrder") ?: 0 ) - }.getOrNull() + } } - fun fromJson(json: String): RssSource? { + fun fromJson(json: String): Result { return fromJsonDoc(jsonPath.parse(json)) } - fun fromJsonArray(jsonArray: String): ArrayList { - val sources = arrayListOf() - val doc = jsonPath.parse(jsonArray).read>("$") - doc.forEach { - val jsonItem = jsonPath.parse(it) - fromJsonDoc(jsonItem)?.let { source -> - sources.add(source) + fun fromJsonArray(jsonArray: String): Result> { + return kotlin.runCatching { + val sources = arrayListOf() + val doc = jsonPath.parse(jsonArray).read>("$") + doc.forEach { + val jsonItem = jsonPath.parse(it) + fromJsonDoc(jsonItem).getOrThrow().let { source -> + sources.add(source) + } } + sources } - return sources } } diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt index 69b63d9a1..e3728eeab 100644 --- a/app/src/main/java/io/legado/app/help/BookHelp.kt +++ b/app/src/main/java/io/legado/app/help/BookHelp.kt @@ -6,14 +6,11 @@ import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource -import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.localBook.LocalBook import io.legado.app.utils.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.async -import kotlinx.coroutines.delay +import kotlinx.coroutines.* +import kotlinx.coroutines.Dispatchers.IO import org.apache.commons.text.similarity.JaccardSimilarity import splitties.init.appCtx import java.io.File @@ -44,11 +41,10 @@ object BookHelp { /** * 清除已删除书的缓存 */ - fun clearRemovedCache() { - Coroutine.async { - val bookFolderNames = arrayListOf() - appDb.bookDao.all.forEach { - bookFolderNames.add(it.getFolderName()) + suspend fun clearInvalidCache() { + withContext(IO) { + val bookFolderNames = appDb.bookDao.all.map { + it.getFolderName() } val file = downloadDir.getFile(cacheFolderName) file.listFiles()?.forEach { bookFile -> diff --git a/app/src/main/java/io/legado/app/help/DefaultData.kt b/app/src/main/java/io/legado/app/help/DefaultData.kt index 774b0ea4c..33ebfb05e 100644 --- a/app/src/main/java/io/legado/app/help/DefaultData.kt +++ b/app/src/main/java/io/legado/app/help/DefaultData.kt @@ -54,13 +54,11 @@ object DefaultData { } val rssSources: List by lazy { - kotlin.runCatching { - val json = String( - appCtx.assets.open("defaultData${File.separator}rssSources.json") - .readBytes() - ) - RssSource.fromJsonArray(json) - }.getOrDefault(emptyList()) + val json = String( + appCtx.assets.open("defaultData${File.separator}rssSources.json") + .readBytes() + ) + RssSource.fromJsonArray(json).getOrDefault(emptyList()) } val coverRuleConfig: BookCover.CoverRuleConfig by lazy { diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index a5229675d..77d38bba9 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -139,7 +139,7 @@ interface JsExtensions { path.startsWith("/storage") -> FileUtils.readText(path) else -> readTxtFile(path) } - if (result.isBlank()) throw NoStackTraceException("${path} 内容获取失败或者为空") + if (result.isBlank()) throw NoStackTraceException("$path 内容获取失败或者为空") return result } diff --git a/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt b/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt index 4db179cf6..b5c461f25 100644 --- a/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt +++ b/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt @@ -7,7 +7,9 @@ import io.legado.app.constant.AppLog import io.legado.app.constant.BookType import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.rule.* +import io.legado.app.exception.NoStackTraceException import io.legado.app.utils.* +import java.io.InputStream import java.util.regex.Pattern @@ -16,31 +18,66 @@ object SourceAnalyzer { private val headerPattern = Pattern.compile("@Header:\\{.+?\\}", Pattern.CASE_INSENSITIVE) private val jsPattern = Pattern.compile("\\{\\{.+?\\}\\}", Pattern.CASE_INSENSITIVE) - fun jsonToBookSources(json: String): List { - val bookSources = mutableListOf() - if (json.isJsonArray()) { - val items: List> = jsonPath.parse(json).read("$") - for (item in items) { + fun jsonToBookSources(json: String): Result> { + return kotlin.runCatching { + val bookSources = mutableListOf() + when { + json.isJsonArray() -> { + val items: List> = jsonPath.parse(json).read("$") + for (item in items) { + val jsonItem = jsonPath.parse(item) + jsonToBookSource(jsonItem.jsonString()).getOrThrow().let { + bookSources.add(it) + } + } + } + json.isJsonObject() -> { + jsonToBookSource(json).getOrThrow().let { + bookSources.add(it) + } + } + else -> { + throw NoStackTraceException("格式不对") + } + } + bookSources + } + } + + fun jsonToBookSources(inputStream: InputStream): Result> { + return kotlin.runCatching { + val bookSources = mutableListOf() + kotlin.runCatching { + val items: List> = jsonPath.parse(inputStream).read("$") + for (item in items) { + val jsonItem = jsonPath.parse(item) + jsonToBookSource(jsonItem.jsonString()).getOrThrow().let { + bookSources.add(it) + } + } + }.onFailure { + val item: Map = jsonPath.parse(inputStream).read("$") val jsonItem = jsonPath.parse(item) - jsonToBookSource(jsonItem.jsonString())?.let { + jsonToBookSource(jsonItem.jsonString()).getOrThrow().let { bookSources.add(it) } } + bookSources } - return bookSources } - fun jsonToBookSource(json: String): BookSource? { + fun jsonToBookSource(json: String): Result { val source = BookSource() val sourceAny = GSON.fromJsonObject(json.trim()) .onFailure { AppLog.put("转化书源出错", it) }.getOrNull() - try { + return kotlin.runCatching { if (sourceAny?.ruleToc == null) { source.apply { val jsonItem = jsonPath.parse(json.trim()) - bookSourceUrl = jsonItem.readString("bookSourceUrl") ?: return null + bookSourceUrl = jsonItem.readString("bookSourceUrl") + ?: throw NoStackTraceException("格式不对") bookSourceName = jsonItem.readString("bookSourceName") ?: "" bookSourceGroup = jsonItem.readString("bookSourceGroup") loginUrl = jsonItem.readString("loginUrl") @@ -168,10 +205,8 @@ object SourceAnalyzer { .getOrNull() } } - } catch (e: Exception) { - e.printOnDebug() + source } - return source } @Keep diff --git a/app/src/main/java/io/legado/app/help/config/AppConfig.kt b/app/src/main/java/io/legado/app/help/config/AppConfig.kt index 25525406f..a851ce134 100644 --- a/app/src/main/java/io/legado/app/help/config/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/config/AppConfig.kt @@ -301,6 +301,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { val doublePageHorizontal: Boolean get() = appCtx.getPrefBoolean(PreferKey.doublePageHorizontal, true) + var searchGroup: String + get() = appCtx.getPrefString("searchGroup") ?: "" + set(value) { + appCtx.putPrefString("searchGroup", value) + } + private fun getPrefUserAgent(): String { val ua = appCtx.getPrefString(PreferKey.userAgent) if (ua.isNullOrBlank()) { diff --git a/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt index 9e157dc1c..1a10c0280 100644 --- a/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt +++ b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt @@ -91,9 +91,10 @@ object ImportOldData { } fun importOldSource(json: String): Int { - val bookSources = BookSource.fromJsonArray(json) - appDb.bookSourceDao.insert(*bookSources.toTypedArray()) - return bookSources.size + val count = BookSource.fromJsonArray(json).onSuccess { + appDb.bookSourceDao.insert(*it.toTypedArray()) + }.getOrNull()?.size + return count ?: 0 } private fun importOldReplaceRule(json: String): Int { diff --git a/app/src/main/java/io/legado/app/help/storage/Restore.kt b/app/src/main/java/io/legado/app/help/storage/Restore.kt index af7660d25..884cb923b 100644 --- a/app/src/main/java/io/legado/app/help/storage/Restore.kt +++ b/app/src/main/java/io/legado/app/help/storage/Restore.kt @@ -22,6 +22,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.withContext import splitties.init.appCtx import java.io.File +import java.io.FileInputStream object Restore { @@ -192,8 +193,9 @@ object Restore { private inline fun fileToListT(path: String, fileName: String): List? { try { val file = FileUtils.createFileIfNotExist(path + File.separator + fileName) - val json = file.readText() - return GSON.fromJsonArray(json).getOrThrow() + FileInputStream(file).use { + return GSON.fromJsonArray(it).getOrThrow() + } } catch (e: Exception) { AppLog.put("$fileName\n读取解析出错\n${e.localizedMessage}", e) appCtx.toastOnUi("$fileName\n读取文件出错\n${e.localizedMessage}") diff --git a/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt b/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt index 5d99e575e..7690a47c3 100644 --- a/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt +++ b/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt @@ -48,9 +48,9 @@ fun Context.alert( inline fun Fragment.alert( titleResource: Int? = null, - message: Int? = null, + messageResource: Int? = null, noinline init: (AlertBuilder.() -> Unit)? = null -) = requireActivity().alert(titleResource, message, init) +) = requireActivity().alert(titleResource, messageResource, init) fun Context.alert(init: AlertBuilder.() -> Unit): AlertDialog = AndroidAlertBuilder(this).apply { diff --git a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt index 4b565d345..6e2d9de8b 100644 --- a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt +++ b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt @@ -1,5 +1,6 @@ package io.legado.app.lib.webdav +import io.legado.app.constant.AppLog import io.legado.app.help.http.newCallResponseBody import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.text @@ -168,6 +169,8 @@ class WebDav(urlStr: String) { addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) }.close() } + }.onFailure { + AppLog.put(it.localizedMessage) }.isSuccess } return false diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index 972e6fc24..59a2221da 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -22,6 +22,7 @@ import javax.script.SimpleBindings object LocalBook { private val nameAuthorPatterns = arrayOf( + Pattern.compile("(.*?)《([^《》]+)》.*?作者:(.*)"), Pattern.compile("(.*?)《([^《》]+)》(.*)"), Pattern.compile("(^)(.+) 作者:(.+)$"), Pattern.compile("(^)(.+) by (.+)$") diff --git a/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt b/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt index 0e92d9acd..c8cc3b82f 100644 --- a/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt +++ b/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt @@ -8,7 +8,6 @@ import io.legado.app.data.entities.SearchBook import io.legado.app.help.config.AppConfig import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.utils.getPrefBoolean -import io.legado.app.utils.getPrefString import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExecutorCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher @@ -60,7 +59,7 @@ class SearchModel(private val scope: CoroutineScope) { initSearchPool() mSearchId = searchId searchPage = 1 - val searchGroup = appCtx.getPrefString("searchGroup") ?: "" + val searchGroup = AppConfig.searchGroup bookSourceList.clear() searchBooks.clear() callBack?.onSearchSuccess(searchBooks) @@ -69,6 +68,7 @@ class SearchModel(private val scope: CoroutineScope) { } else { val sources = appDb.bookSourceDao.getEnabledByGroup(searchGroup) if (sources.isEmpty()) { + AppConfig.searchGroup = "" bookSourceList.addAll(appDb.bookSourceDao.allEnabled) } else { bookSourceList.addAll(sources) diff --git a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt index 60665c3b3..04234cbd0 100644 --- a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt +++ b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt @@ -262,7 +262,7 @@ object WebBook { Debug.log(bookSource.bookSourceUrl, "⇒正文规则为空,使用章节链接:${bookChapter.url}") return bookChapter.url } - if(bookChapter.isVolume && bookChapter.url.startsWith(bookChapter.title)) { + if (bookChapter.isVolume && bookChapter.url.startsWith(bookChapter.title)) { Debug.log(bookSource.bookSourceUrl, "⇒一级目录正文不解析规则") return bookChapter.tag ?: "" } @@ -320,35 +320,38 @@ object WebBook { name: String, author: String, context: CoroutineContext = Dispatchers.IO, - ): Coroutine> { + ): Coroutine> { return Coroutine.async(scope, context) { - preciseSearchAwait(scope, bookSources, name, author) - ?: throw NoStackTraceException("没有搜索到<$name>$author") + for (source in bookSources) { + val book = preciseSearchAwait(scope, source, name, author).getOrNull() + if (book != null) { + return@async Pair(book, source) + } + } + throw NoStackTraceException("没有搜索到<$name>$author") } } suspend fun preciseSearchAwait( scope: CoroutineScope, - bookSources: List, + bookSource: BookSource, name: String, - author: String - ): Pair? { - bookSources.forEach { source -> - kotlin.runCatching { - if (!scope.isActive) return null - searchBookAwait(scope, source, name).firstOrNull { - it.name == name && it.author == author - }?.let { searchBook -> - if (!scope.isActive) return null - var book = searchBook.toBook() - if (book.tocUrl.isBlank()) { - book = getBookInfoAwait(scope, source, book) - } - return Pair(source, book) + author: String, + ): Result { + return kotlin.runCatching { + if (!scope.isActive) return@runCatching null + searchBookAwait(scope, bookSource, name).firstOrNull { + it.name == name && it.author == author + }?.let { searchBook -> + if (!scope.isActive) return@runCatching null + var book = searchBook.toBook() + if (book.tocUrl.isBlank()) { + book = getBookInfoAwait(scope, bookSource, book) } + return@runCatching book } + return@runCatching null } - return null } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt b/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt index 85ac06534..3726127ff 100644 --- a/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt @@ -31,9 +31,8 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo } else { DocumentFile.fromSingleUri(context, uri)?.readText(context) } ?: throw NoStackTraceException("文件不存在") - if (content.isJson()) { - //暂时根据文件内容判断属于什么 - when { + when { + content.isJson() -> when { content.contains("bookSourceUrl") -> importBookSourceLive.postValue(content) content.contains("sourceUrl") -> @@ -48,10 +47,12 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo importHttpTTS(content, finally) else -> errorLiveData.postValue("格式不对") } - } else if (uri.toString().matches(bookFileRegex)) { - importBookLiveData.postValue(uri) - } else { - throw NoStackTraceException("暂未支持的本地书籍格式(TXT/UMD/EPUB)") + (uri.path ?: uri.toString()).matches(bookFileRegex) -> { + importBookLiveData.postValue(uri) + } + else -> { + throw NoStackTraceException("暂未支持的本地书籍格式(TXT/UMD/EPUB)") + } } } else { onLineImportLive.postValue(uri) diff --git a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt index 9892ba503..a6aacbfd3 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt @@ -189,7 +189,7 @@ class ImportBookSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_vie override fun onCodeSave(code: String, requestId: String?) { requestId?.toInt()?.let { - BookSource.fromJson(code)?.let { source -> + BookSource.fromJson(code).getOrNull()?.let { source -> viewModel.allSources[it] = source adapter.setItem(it, source) } diff --git a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt index 6d1a97dde..93cc32bc0 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt @@ -14,7 +14,6 @@ import io.legado.app.help.SourceHelp import io.legado.app.help.config.AppConfig import io.legado.app.help.http.newCallResponseBody import io.legado.app.help.http.okHttpClient -import io.legado.app.help.http.text import io.legado.app.utils.* @@ -98,13 +97,12 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) { importSourceUrl(it) } } else { - BookSource.fromJson(mText)?.let { + BookSource.fromJson(mText).getOrThrow().let { allSources.add(it) } } } - mText.isJsonArray() -> { - val items = BookSource.fromJsonArray(mText) + mText.isJsonArray() -> BookSource.fromJsonArray(mText).getOrThrow().let { items -> allSources.addAll(items) } mText.isAbsUrl() -> { @@ -123,26 +121,8 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) { private suspend fun importSourceUrl(url: String) { okHttpClient.newCallResponseBody { url(url) - }.text("utf-8").let { body -> - when { - body.isJsonArray() -> { - val items: List> = jsonPath.parse(body).read("$") - for (item in items) { - val jsonItem = jsonPath.parse(item) - BookSource.fromJson(jsonItem.jsonString())?.let { source -> - allSources.add(source) - } - } - } - body.isJsonObject() -> { - BookSource.fromJson(body)?.let { - allSources.add(it) - } - } - else -> { - throw NoStackTraceException(context.getString(R.string.wrong_format)) - } - } + }.byteStream().let { + allSources.addAll(BookSource.fromJsonArray(it).getOrThrow()) } } diff --git a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt index 8ac19ba45..830f0941d 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt @@ -92,14 +92,14 @@ class ImportRssSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_view adapter.notifyDataSetChanged() upSelectText() } - viewModel.errorLiveData.observe(this, { + viewModel.errorLiveData.observe(this) { binding.rotateLoading.hide() binding.tvMsg.apply { text = it visible() } - }) - viewModel.successLiveData.observe(this, { + } + viewModel.successLiveData.observe(this) { binding.rotateLoading.hide() if (it > 0) { adapter.setItems(viewModel.allSources) @@ -110,7 +110,7 @@ class ImportRssSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_view visible() } } - }) + } val source = arguments?.getString("source") if (source.isNullOrEmpty()) { dismiss() @@ -188,7 +188,7 @@ class ImportRssSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_view override fun onCodeSave(code: String, requestId: String?) { requestId?.toInt()?.let { - RssSource.fromJson(code)?.let { source -> + RssSource.fromJson(code).getOrNull()?.let { source -> viewModel.allSources[it] = source adapter.setItem(it, source) } diff --git a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt index cbfaf03e7..d44414c9a 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt @@ -13,7 +13,6 @@ import io.legado.app.help.SourceHelp import io.legado.app.help.config.AppConfig import io.legado.app.help.http.newCallResponseBody import io.legado.app.help.http.okHttpClient -import io.legado.app.help.http.text import io.legado.app.utils.* class ImportRssSourceViewModel(app: Application) : BaseViewModel(app) { @@ -95,7 +94,7 @@ class ImportRssSourceViewModel(app: Application) : BaseViewModel(app) { importSourceUrl(it) } } else { - RssSource.fromJsonArray(mText).let { + RssSource.fromJsonArray(mText).getOrThrow().let { allSources.addAll(it) } } @@ -104,7 +103,7 @@ class ImportRssSourceViewModel(app: Application) : BaseViewModel(app) { val items: List> = jsonPath.parse(mText).read("$") for (item in items) { val jsonItem = jsonPath.parse(item) - RssSource.fromJsonDoc(jsonItem)?.let { + RssSource.fromJsonDoc(jsonItem).getOrThrow().let { allSources.add(it) } } @@ -124,11 +123,11 @@ class ImportRssSourceViewModel(app: Application) : BaseViewModel(app) { private suspend fun importSourceUrl(url: String) { okHttpClient.newCallResponseBody { url(url) - }.text("utf-8").let { body -> + }.byteStream().let { body -> val items: List> = jsonPath.parse(body).read("$") for (item in items) { val jsonItem = jsonPath.parse(item) - RssSource.fromJson(jsonItem.jsonString())?.let { source -> + RssSource.fromJson(jsonItem.jsonString()).getOrThrow().let { source -> allSources.add(source) } } diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt index 4b429ad6d..85c67d54c 100644 --- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt @@ -15,11 +15,13 @@ import io.legado.app.constant.PreferKey import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookGroup +import io.legado.app.data.entities.BookSource import io.legado.app.databinding.ActivityArrangeBookBinding import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.book.group.GroupManageDialog import io.legado.app.ui.book.group.GroupSelectDialog +import io.legado.app.ui.theme.AppTheme import io.legado.app.ui.widget.SelectActionBar import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback @@ -41,6 +43,7 @@ class ArrangeBookActivity : VMBaseActivity viewModel.upCanUpdate(adapter.selectedBooks(), false) R.id.menu_add_to_group -> selectGroup(addToGroupRequestCode, 0) + R.id.menu_change_source -> showDialogFragment() } return false } @@ -228,4 +243,9 @@ class ArrangeBookActivity : VMBaseActivity? = null + fun upCanUpdate(books: Array, canUpdate: Boolean) { execute { books.forEach { @@ -29,4 +38,24 @@ class ArrangeBookViewModel(application: Application) : BaseViewModel(application } } + fun changeSource(books: Array, source: BookSource) { + batchChangeSourceCoroutine?.cancel() + batchChangeSourceCoroutine = execute { + batchChangeSourceSize.value = books.size + books.forEachIndexed { index, book -> + batchChangeSourcePosition.value = index + 1 + if (book.isLocalBook()) return@forEachIndexed + if (book.origin == source.bookSourceUrl) return@forEachIndexed + WebBook.preciseSearchAwait(this, source, book.name, book.author) + .getOrNull()?.let { newBook -> + val toc = WebBook.getChapterListAwait(this, source, newBook) + book.changeTo(newBook, toc) + appDb.bookChapterDao.insert(*toc.toTypedArray()) + } + } + }.onFinally { + batchChangeSourceState.value = false + } + } + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ComposeView.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ComposeView.kt new file mode 100644 index 000000000..bfb86ed15 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/arrange/ComposeView.kt @@ -0,0 +1,45 @@ +package io.legado.app.ui.book.arrange + +import androidx.compose.foundation.layout.Column +import androidx.compose.material.AlertDialog +import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.Text +import androidx.compose.material.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Alignment +import io.legado.app.R +import splitties.init.appCtx + +@Composable +fun BatchChangeSourceDialog( + state: MutableState, + size: MutableState, + position: MutableState, + cancel: () -> Unit +) { + if (state.value) { + AlertDialog( + onDismissRequest = { }, + confirmButton = { + TextButton(onClick = { + cancel.invoke() + state.value = false + }, content = { + Text(text = "取消") + }) + }, + title = { + Text(text = appCtx.getString(R.string.change_source_batch)) + }, + text = { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text(text = "${position.value}/${size.value}") + LinearProgressIndicator( + progress = position.value / size.value.toFloat() + ) + } + } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/SourcePickerDialog.kt b/app/src/main/java/io/legado/app/ui/book/arrange/SourcePickerDialog.kt new file mode 100644 index 000000000..50101e9a6 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/arrange/SourcePickerDialog.kt @@ -0,0 +1,121 @@ +package io.legado.app.ui.book.arrange + +import android.content.Context +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.widget.SearchView +import androidx.core.view.setPadding +import androidx.recyclerview.widget.LinearLayoutManager +import io.legado.app.R +import io.legado.app.base.BaseDialogFragment +import io.legado.app.base.adapter.ItemViewHolder +import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.appDb +import io.legado.app.data.entities.BookSource +import io.legado.app.databinding.DialogSourcePickerBinding +import io.legado.app.databinding.Item1lineTextBinding +import io.legado.app.lib.theme.primaryColor +import io.legado.app.lib.theme.primaryTextColor +import io.legado.app.utils.applyTint +import io.legado.app.utils.dpToPx +import io.legado.app.utils.setLayout +import io.legado.app.utils.viewbindingdelegate.viewBinding +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import splitties.views.onClick + +class SourcePickerDialog : BaseDialogFragment(R.layout.dialog_source_picker) { + + private val binding by viewBinding(DialogSourcePickerBinding::bind) + private val searchView: SearchView by lazy { + binding.toolBar.findViewById(R.id.search_view) + } + private val adapter by lazy { + SourceAdapter(requireContext()) + } + private var sourceFlowJob: Job? = null + + override fun onStart() { + super.onStart() + setLayout(1f, ViewGroup.LayoutParams.MATCH_PARENT) + } + + override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { + initView() + initData() + } + + private fun initView() { + binding.toolBar.setBackgroundColor(primaryColor) + binding.toolBar.title = "选择书源" + binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) + binding.recyclerView.adapter = adapter + searchView.applyTint(primaryTextColor) + searchView.onActionViewExpanded() + searchView.isSubmitButtonEnabled = true + searchView.queryHint = getString(R.string.search_book_source) + searchView.clearFocus() + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?): Boolean { + return false + } + + override fun onQueryTextChange(newText: String?): Boolean { + initData(newText) + return false + } + }) + } + + private fun initData(searchKey: String? = null) { + sourceFlowJob?.cancel() + sourceFlowJob = launch { + when { + searchKey.isNullOrEmpty() -> appDb.bookSourceDao.flowEnabled() + else -> appDb.bookSourceDao.flowSearchEnabled(searchKey) + }.collect { + adapter.setItems(it) + } + } + } + + inner class SourceAdapter(context: Context) : + RecyclerAdapter(context) { + + override fun getViewBinding(parent: ViewGroup): Item1lineTextBinding { + return Item1lineTextBinding.inflate(inflater, parent, false).apply { + root.setPadding(16.dpToPx()) + } + } + + override fun convert( + holder: ItemViewHolder, + binding: Item1lineTextBinding, + item: BookSource, + payloads: MutableList + ) { + binding.textView.text = item.getDisPlayNameGroup() + } + + override fun registerListener(holder: ItemViewHolder, binding: Item1lineTextBinding) { + binding.root.onClick { + getItemByLayoutPosition(holder.layoutPosition)?.let { + callback?.sourceOnClick(it) + dismissAllowingStateLoss() + } + } + } + + } + + private val callback: Callback? + get() { + return (parentFragment as? Callback) ?: activity as? Callback + } + + interface Callback { + fun sourceOnClick(source: BookSource) + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayActivity.kt b/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayActivity.kt index 7c2b23e03..4f9b53240 100644 --- a/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayActivity.kt @@ -12,10 +12,12 @@ import androidx.activity.viewModels import androidx.compose.runtime.mutableStateOf import io.legado.app.R import io.legado.app.base.VMBaseActivity +import io.legado.app.constant.BookType import io.legado.app.constant.EventBus import io.legado.app.constant.Status import io.legado.app.constant.Theme import io.legado.app.data.entities.Book +import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource import io.legado.app.databinding.ActivityAudioPlayBinding import io.legado.app.lib.dialogs.alert @@ -24,6 +26,7 @@ import io.legado.app.model.BookCover import io.legado.app.service.AudioPlayService import io.legado.app.ui.about.AppLogDialog import io.legado.app.ui.book.changesource.ChangeBookSourceDialog +import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.book.toc.TocActivityResult import io.legado.app.ui.login.SourceLoginActivity @@ -31,6 +34,9 @@ import io.legado.app.ui.theme.AppTheme import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import splitties.views.onLongClick import java.util.* @@ -198,8 +204,21 @@ class AudioPlayActivity : override val oldBook: Book? get() = AudioPlay.book - override fun changeTo(source: BookSource, book: Book) { - viewModel.changeTo(source, book) + override fun changeTo(source: BookSource, book: Book, toc: List) { + if (book.type == BookType.audio) { + viewModel.changeTo(source, book, toc) + } else { + AudioPlay.stop(this) + launch { + withContext(IO) { + AudioPlay.book?.changeTo(book, toc) + } + startActivity { + putExtra("bookUrl", book.bookUrl) + } + finish() + } + } } override fun finish() { diff --git a/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayViewModel.kt b/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayViewModel.kt index 2550c9feb..4ea1acad5 100644 --- a/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/audio/AudioPlayViewModel.kt @@ -9,8 +9,6 @@ import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource -import io.legado.app.help.BookHelp -import io.legado.app.help.ContentProcessor import io.legado.app.model.AudioPlay import io.legado.app.model.webBook.WebBook import io.legado.app.utils.postEvent @@ -45,33 +43,23 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) } } - private fun loadBookInfo( - book: Book, - changeDruChapterIndex: ((chapters: List) -> Unit)? = null - ) { + private fun loadBookInfo(book: Book) { execute { AudioPlay.bookSource?.let { WebBook.getBookInfo(this, it, book) .onSuccess { - loadChapterList(book, changeDruChapterIndex) + loadChapterList(book) } } } } - private fun loadChapterList( - book: Book, - changeDruChapterIndex: ((chapters: List) -> Unit)? = null - ) { + private fun loadChapterList(book: Book) { execute { AudioPlay.bookSource?.let { WebBook.getChapterList(this, it, book) .onSuccess(Dispatchers.IO) { cList -> - if (changeDruChapterIndex == null) { - appDb.bookChapterDao.insert(*cList.toTypedArray()) - } else { - changeDruChapterIndex(cList) - } + appDb.bookChapterDao.insert(*cList.toTypedArray()) AudioPlay.upDurChapter(book) }.onError { context.toastOnUi(R.string.error_load_toc) @@ -88,47 +76,17 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) } } - fun changeTo(source: BookSource, book: Book) { + fun changeTo(source: BookSource, book: Book, toc: List) { execute { - var oldTocSize: Int = book.totalChapterNum - AudioPlay.book?.let { - oldTocSize = it.totalChapterNum - book.order = it.order - appDb.bookDao.delete(it) - } - appDb.bookDao.insert(book) - AudioPlay.book = book + AudioPlay.book = AudioPlay.book!!.changeTo(book, toc) AudioPlay.bookSource = source - if (book.tocUrl.isEmpty()) { - loadBookInfo(book) { upChangeDurChapterIndex(book, oldTocSize, it) } - } else { - loadChapterList(book) { upChangeDurChapterIndex(book, oldTocSize, it) } - } + appDb.bookChapterDao.insert(*toc.toTypedArray()) + AudioPlay.upDurChapter(book) }.onFinally { postEvent(EventBus.SOURCE_CHANGED, book.bookUrl) } } - private fun upChangeDurChapterIndex( - book: Book, - oldTocSize: Int, - chapters: List - ) { - execute { - book.durChapterIndex = BookHelp.getDurChapter( - book.durChapterIndex, - book.durChapterTitle, - chapters, - oldTocSize - ) - book.durChapterTitle = chapters[book.durChapterIndex].getDisplayTitle( - ContentProcessor.get(book.name, book.origin).getTitleReplaceRules() - ) - appDb.bookDao.update(book) - appDb.bookChapterDao.insert(*chapters.toTypedArray()) - } - } - fun removeFromBookshelf(success: (() -> Unit)?) { execute { AudioPlay.book?.let { diff --git a/app/src/main/java/io/legado/app/ui/book/audio/ComposeView.kt b/app/src/main/java/io/legado/app/ui/book/audio/ComposeView.kt index 146509f9e..e1a262314 100644 --- a/app/src/main/java/io/legado/app/ui/book/audio/ComposeView.kt +++ b/app/src/main/java/io/legado/app/ui/book/audio/ComposeView.kt @@ -32,7 +32,7 @@ fun TimerDialog(state: MutableState, parent: View) { timeMinute.value = it.toInt() AudioPlay.setTimer(it.toInt()) }, - valueRange = 0f..180f + valueRange = 0f..180f, ) } } diff --git a/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkActivity.kt b/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkActivity.kt new file mode 100644 index 000000000..1d7eb937b --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkActivity.kt @@ -0,0 +1,47 @@ +package io.legado.app.ui.book.bookmark + +import android.os.Bundle +import androidx.activity.viewModels +import io.legado.app.base.VMBaseActivity +import io.legado.app.data.entities.Bookmark +import io.legado.app.databinding.ActivityAllBookmarkBinding +import io.legado.app.utils.showDialogFragment +import io.legado.app.utils.viewbindingdelegate.viewBinding + +class AllBookmarkActivity : VMBaseActivity(), + BookmarkAdapter.Callback, + BookmarkDialog.Callback { + + override val viewModel by viewModels() + override val binding by viewBinding(ActivityAllBookmarkBinding::inflate) + private val adapter by lazy { + BookmarkAdapter(this, this) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + initView() + viewModel.initData { + adapter.setItems(it) + } + } + + private fun initView() { + binding.recyclerView.addItemDecoration(BookmarkDecoration(adapter)) + binding.recyclerView.adapter = adapter + } + + override fun onItemClick(bookmark: Bookmark, position: Int) { + showDialogFragment(BookmarkDialog(bookmark, position)) + } + + override fun upBookmark(pos: Int, bookmark: Bookmark) { + adapter.setItem(pos, bookmark) + } + + override fun deleteBookmark(pos: Int) { + adapter.getItem(pos)?.let { + viewModel.deleteBookmark(it) + } + adapter.removeItem(pos) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkViewModel.kt b/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkViewModel.kt new file mode 100644 index 000000000..f395319fb --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkViewModel.kt @@ -0,0 +1,25 @@ +package io.legado.app.ui.book.bookmark + +import android.app.Application +import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb +import io.legado.app.data.entities.Bookmark + +class AllBookmarkViewModel(application: Application) : BaseViewModel(application) { + + + fun initData(onSuccess: (bookmarks: List) -> Unit) { + execute { + appDb.bookmarkDao.all + }.onSuccess { + onSuccess.invoke(it) + } + } + + fun deleteBookmark(bookmark: Bookmark) { + execute { + appDb.bookmarkDao.delete(bookmark) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkAdapter.kt b/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkAdapter.kt new file mode 100644 index 000000000..7db9ea6ed --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkAdapter.kt @@ -0,0 +1,60 @@ +package io.legado.app.ui.book.bookmark + +import android.content.Context +import android.view.ViewGroup +import io.legado.app.base.adapter.ItemViewHolder +import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.entities.Bookmark +import io.legado.app.databinding.ItemBookmarkBinding +import io.legado.app.utils.gone +import splitties.views.onClick + +class BookmarkAdapter(context: Context, val callback: Callback) : + RecyclerAdapter(context) { + + override fun getViewBinding(parent: ViewGroup): ItemBookmarkBinding { + return ItemBookmarkBinding.inflate(inflater, parent, false) + } + + override fun convert( + holder: ItemViewHolder, + binding: ItemBookmarkBinding, + item: Bookmark, + payloads: MutableList + ) { + binding.tvChapterName.text = item.chapterName + binding.tvBookText.gone(item.bookText.isEmpty()) + binding.tvBookText.text = item.bookText + binding.tvContent.gone(item.content.isEmpty()) + binding.tvContent.text = item.content + } + + override fun registerListener(holder: ItemViewHolder, binding: ItemBookmarkBinding) { + binding.root.onClick { + getItemByLayoutPosition(holder.layoutPosition)?.let { + callback.onItemClick(it, holder.layoutPosition) + } + } + } + + fun getHeaderText(position: Int): String { + return with(getItem(position)) { + "${this?.bookName ?: ""}(${this?.bookAuthor ?: ""})" + } + } + + fun isItemHeader(position: Int): Boolean { + if (position == 0) return true + val lastItem = getItem(position - 1) + val curItem = getItem(position) + return !(lastItem?.bookName == curItem?.bookName + && lastItem?.bookAuthor == curItem?.bookAuthor) + } + + interface Callback { + + fun onItemClick(bookmark: Bookmark, position: Int) + + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkDecoration.kt b/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkDecoration.kt new file mode 100644 index 000000000..ed18041bf --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkDecoration.kt @@ -0,0 +1,110 @@ +package io.legado.app.ui.book.bookmark + +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.text.TextPaint +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import io.legado.app.lib.theme.accentColor +import io.legado.app.lib.theme.backgroundColor +import io.legado.app.utils.dpToPx +import io.legado.app.utils.spToPx +import splitties.init.appCtx +import kotlin.math.min + +class BookmarkDecoration(val adapter: BookmarkAdapter) : RecyclerView.ItemDecoration() { + + private val headerLeft = 16f.dpToPx() + private val headerHeight = 32f.dpToPx() + + private val headerPaint = Paint().apply { + color = appCtx.backgroundColor + } + private val textPaint = TextPaint().apply { + textSize = 16f.spToPx() + color = appCtx.accentColor + } + private val textRect = Rect() + + override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val count = parent.childCount + for (i in 0 until count) { + val view = parent.getChildAt(i) + val position = parent.getChildLayoutPosition(view) + val isHeader = adapter.isItemHeader(position) + if (isHeader) { + c.drawRect( + 0f, + view.top - headerHeight, + parent.width.toFloat(), + view.top.toFloat(), + headerPaint + ) + val headerText = adapter.getHeaderText(position) + textPaint.getTextBounds(headerText, 0, headerText.length, textRect) + c.drawText( + headerText, + headerLeft, + (view.top - headerHeight) + headerHeight / 2 + textRect.height() / 2, + textPaint + ) + } + } + } + + override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val position = (parent.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() + val view = parent.findViewHolderForAdapterPosition(position)?.itemView ?: return + val isHeader = adapter.isItemHeader(position + 1) + val headerText = adapter.getHeaderText(position) + if (isHeader) { + val bottom = min(headerHeight.toInt(), view.bottom) + c.drawRect( + 0f, + view.top - headerHeight, + parent.width.toFloat(), + bottom.toFloat(), + headerPaint + ) + textPaint.getTextBounds(headerText, 0, headerText.length, textRect) + c.drawText( + headerText, + headerLeft, + headerHeight / 2 + textRect.height() / 2 - (headerHeight - bottom), + textPaint + ) + } else { + c.drawRect( + 0f, + 0f, + parent.width.toFloat(), + headerHeight, + headerPaint + ) + textPaint.getTextBounds(headerText, 0, headerText.length, textRect) + c.drawText( + headerText, + headerLeft, + headerHeight / 2 + textRect.height() / 2, + textPaint + ) + } + c.save() + } + + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + val position = parent.getChildLayoutPosition(view) + val isHeader = adapter.isItemHeader(position) + if (isHeader) { + outRect.top = headerHeight.toInt() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkDialog.kt b/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkDialog.kt similarity index 94% rename from app/src/main/java/io/legado/app/ui/book/toc/BookmarkDialog.kt rename to app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkDialog.kt index 9457f8309..f31fb9f8b 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/bookmark/BookmarkDialog.kt @@ -1,4 +1,4 @@ -package io.legado.app.ui.book.toc +package io.legado.app.ui.book.bookmark import android.os.Bundle import android.view.View @@ -75,8 +75,9 @@ class BookmarkDialog() : BaseDialogFragment(R.layout.dialog_bookmark) { } } - fun getCallback(): Callback? { - return parentFragment as? Callback + private fun getCallback(): Callback? { + return (parentFragment as? Callback) + ?: activity as? Callback } interface Callback { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceAdapter.kt index 5a653b53d..00a3b9f30 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceAdapter.kt @@ -74,7 +74,9 @@ class ChangeBookSourceAdapter( override fun registerListener(holder: ItemViewHolder, binding: ItemChangeSourceBinding) { holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { - callBack.changeTo(it) + if (it.bookUrl != callBack.bookUrl) { + callBack.changeTo(it) + } } } holder.itemView.onLongClick { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt index a1197acd8..1ebcb9e1b 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt @@ -19,6 +19,7 @@ import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey import io.legado.app.data.appDb import io.legado.app.data.entities.Book +import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.DialogBookChangeSourceBinding @@ -27,6 +28,7 @@ import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.book.source.manage.BookSourceActivity +import io.legado.app.ui.widget.dialog.WaitDialog import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding @@ -50,6 +52,7 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ private val groups = linkedSetOf() private val callBack: CallBack? get() = activity as? CallBack private val viewModel: ChangeBookSourceViewModel by viewModels() + private val waitDialog by lazy { WaitDialog(requireContext()) } private val adapter by lazy { ChangeBookSourceAdapter(requireContext(), viewModel, this) } private val editSourceResult = registerForActivityResult(StartActivityContract(BookSourceEditActivity::class.java)) { @@ -57,14 +60,14 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ } private val searchFinishCallback: (isEmpty: Boolean) -> Unit = { if (it) { - val searchGroup = getPrefString("searchGroup") - if (!searchGroup.isNullOrEmpty()) { + val searchGroup = AppConfig.searchGroup + if (searchGroup.isNotEmpty()) { launch { alert("搜索结果为空") { setMessage("${searchGroup}分组搜索结果为空,是否切换到全部分组") cancelButton() okButton { - putPrefString("searchGroup", "") + AppConfig.searchGroup = "" viewModel.startSearch() } } @@ -218,9 +221,9 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ if (!item.isChecked) { item.isChecked = true if (item.title.toString() == getString(R.string.all_source)) { - putPrefString("searchGroup", "") + AppConfig.searchGroup = "" } else { - putPrefString("searchGroup", item.title.toString()) + AppConfig.searchGroup = item.title.toString() } viewModel.startOrStopSearch() viewModel.refresh() @@ -241,8 +244,23 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ } override fun changeTo(searchBook: SearchBook) { - changeSource(searchBook) - dismissAllowingStateLoss() + if (searchBook.type == callBack?.oldBook?.type) { + changeSource(searchBook) { + dismissAllowingStateLoss() + } + } else { + alert( + titleResource = R.string.book_type_different, + messageResource = R.string.soure_change_source + ) { + okButton { + changeSource(searchBook) { + dismissAllowingStateLoss() + } + } + cancelButton() + } + } } override val bookUrl: String? @@ -269,22 +287,23 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ override fun deleteSource(searchBook: SearchBook) { viewModel.del(searchBook) if (bookUrl == searchBook.bookUrl) { - viewModel.firstSourceOrNull(searchBook)?.let { - changeSource(it) + viewModel.autoChangeSource(callBack?.oldBook?.type) { book, toc, source -> + callBack?.changeTo(source, book, toc) } } } - private fun changeSource(searchBook: SearchBook) { - try { - val book = searchBook.toBook() - book.upInfoFromOld(callBack?.oldBook) - val source = appDb.bookSourceDao.getBookSource(book.origin) - callBack?.changeTo(source!!, book) - searchBook.time = System.currentTimeMillis() - viewModel.updateSource(searchBook) - } catch (e: Exception) { - toastOnUi("换源失败\n${e.localizedMessage}") + private fun changeSource(searchBook: SearchBook, onSuccess: (() -> Unit)? = null) { + waitDialog.setText(R.string.load_toc) + waitDialog.show() + val book = searchBook.toBook() + viewModel.getToc(book, { + waitDialog.dismiss() + toastOnUi(it) + }) { toc, source -> + waitDialog.dismiss() + callBack?.changeTo(source, book, toc) + onSuccess?.invoke() } } @@ -293,7 +312,7 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ */ private fun upGroupMenu() { val menu: Menu = binding.toolBar.menu - val selectedGroup = getPrefString("searchGroup") + val selectedGroup = AppConfig.searchGroup menu.removeGroup(R.id.source_group) val allItem = menu.add(R.id.source_group, Menu.NONE, Menu.NONE, R.string.all_source) var hasSelectedGroup = false @@ -325,7 +344,7 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ interface CallBack { val oldBook: Book? - fun changeTo(source: BookSource, book: Book) + fun changeTo(source: BookSource, book: Book, toc: List) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt index 9234eaa2b..f3f1985a7 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt @@ -11,14 +11,16 @@ import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey import io.legado.app.data.appDb import io.legado.app.data.entities.Book +import io.legado.app.data.entities.BookChapter 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.coroutine.CompositeCoroutine import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.webBook.WebBook import io.legado.app.utils.getPrefBoolean -import io.legado.app.utils.getPrefString +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.ExecutorCoroutineDispatcher @@ -27,8 +29,9 @@ import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map -import splitties.init.appCtx +import kotlinx.coroutines.withContext import java.util.* +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Executors import kotlin.math.min @@ -44,7 +47,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a private var screenKey: String = "" private var bookSourceList = arrayListOf() private val searchBooks = Collections.synchronizedList(arrayListOf()) - private val searchGroup get() = appCtx.getPrefString("searchGroup") ?: "" + private val tocMap = ConcurrentHashMap>() private var searchCallback: SourceCallback? = null val searchDataFlow = callbackFlow { @@ -86,6 +89,11 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a @Volatile private var searchIndex = -1 + override fun onCleared() { + super.onCleared() + searchPool?.close() + } + @CallSuper open fun initData(arguments: Bundle?) { arguments?.let { bundle -> @@ -118,11 +126,13 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a appDb.searchBookDao.clear(name, author) searchBooks.clear() bookSourceList.clear() + val searchGroup = AppConfig.searchGroup if (searchGroup.isBlank()) { bookSourceList.addAll(appDb.bookSourceDao.allEnabled) } else { val sources = appDb.bookSourceDao.getEnabledByGroup(searchGroup) if (sources.isEmpty()) { + AppConfig.searchGroup = "" bookSourceList.addAll(appDb.bookSourceDao.allEnabled) } else { bookSourceList.addAll(sources) @@ -187,6 +197,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a private suspend fun loadBookToc(scope: CoroutineScope, source: BookSource, book: Book) { val chapters = WebBook.getChapterListAwait(scope, source, book) + tocMap[book.bookUrl] = chapters book.latestChapterTitle = chapters.last().title val searchBook: SearchBook = book.toSearchBook() searchCallback?.searchSuccess(searchBook) @@ -212,15 +223,23 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a private fun getDbSearchBooks(): List { return if (screenKey.isEmpty()) { if (AppConfig.changeSourceCheckAuthor) { - appDb.searchBookDao.getChangeSourceSearch(name, author, searchGroup) + appDb.searchBookDao.getChangeSourceSearch( + name, author, AppConfig.searchGroup + ) } else { - appDb.searchBookDao.getChangeSourceSearch(name, "", searchGroup) + appDb.searchBookDao.getChangeSourceSearch( + name, "", AppConfig.searchGroup + ) } } else { if (AppConfig.changeSourceCheckAuthor) { - appDb.searchBookDao.getChangeSourceSearch(name, author, screenKey, searchGroup) + appDb.searchBookDao.getChangeSourceSearch( + name, author, screenKey, AppConfig.searchGroup + ) } else { - appDb.searchBookDao.getChangeSourceSearch(name, "", screenKey, searchGroup) + appDb.searchBookDao.getChangeSourceSearch( + name, "", screenKey, AppConfig.searchGroup + ) } } } @@ -253,9 +272,39 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a searchStateData.postValue(false) } - override fun onCleared() { - super.onCleared() - searchPool?.close() + fun getToc( + book: Book, + onError: (msg: String) -> Unit, + onSuccess: (toc: List, source: BookSource) -> Unit + ) { + execute { + val toc = tocMap[book.bookUrl] + if (toc != null) { + val source = appDb.bookSourceDao.getBookSource(book.origin) + return@execute Pair(toc, source!!) + } + val result = getToc(book).getOrThrow() + tocMap[book.bookUrl] = result.first + return@execute result + }.onSuccess { + onSuccess.invoke(it.first, it.second) + }.onError { + onError.invoke(it.localizedMessage ?: "获取目录出错") + } + } + + suspend fun getToc(book: Book): Result, BookSource>> { + return kotlin.runCatching { + withContext(IO) { + val source = appDb.bookSourceDao.getBookSource(book.origin) + ?: throw NoStackTraceException("书源不存在") + if (book.tocUrl.isEmpty()) { + WebBook.getBookInfoAwait(this, source, book) + } + val toc = WebBook.getChapterListAwait(this, source, book) + Pair(toc, source) + } + } } fun disableSource(searchBook: SearchBook) { @@ -310,8 +359,26 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a searchCallback?.upAdapter() } - fun firstSourceOrNull(searchBook: SearchBook): SearchBook? { - return searchBooks.firstOrNull { it.bookUrl != searchBook.bookUrl } + fun autoChangeSource( + bookType: Int?, + onSuccess: (book: Book, toc: List, source: BookSource) -> Unit + ) { + execute { + searchBooks.forEach { + if (it.type == bookType) { + val book = it.toBook() + val result = getToc(book).getOrNull() + if (result != null) { + return@execute Triple(book, result.first, result.second) + } + } + } + throw NoStackTraceException("没有有效源") + }.onSuccess { + onSuccess.invoke(it.first, it.second, it.third) + }.onError { + context.toastOnUi("自动换源失败\n${it.localizedMessage}") + } } interface SourceCallback { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt index a819b15d6..21b61822e 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt @@ -67,13 +67,6 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c private val tocAdapter by lazy { ChangeChapterTocAdapter(requireContext(), this) } - private val tocSuccess: (toc: List) -> Unit = { - tocAdapter.durChapterIndex = - BookHelp.getDurChapter(viewModel.chapterIndex, viewModel.chapterTitle, it) - binding.loadingToc.hide() - tocAdapter.setItems(it) - binding.recyclerViewToc.scrollToPosition(tocAdapter.durChapterIndex - 5) - } private val contentSuccess: (content: String) -> Unit = { binding.loadingToc.hide() callBack?.replaceContent(it) @@ -82,14 +75,14 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c private var searchBook: SearchBook? = null private val searchFinishCallback: (isEmpty: Boolean) -> Unit = { if (it) { - val searchGroup = getPrefString("searchGroup") - if (!searchGroup.isNullOrEmpty()) { + val searchGroup = AppConfig.searchGroup + if (searchGroup.isNotEmpty()) { launch { alert("搜索结果为空") { setMessage("${searchGroup}分组搜索结果为空,是否切换到全部分组") cancelButton() okButton { - putPrefString("searchGroup", "") + AppConfig.searchGroup = "" viewModel.startSearch() } } @@ -252,9 +245,9 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c if (!item.isChecked) { item.isChecked = true if (item.title.toString() == getString(R.string.all_source)) { - putPrefString("searchGroup", "") + AppConfig.searchGroup = "" } else { - putPrefString("searchGroup", item.title.toString()) + AppConfig.searchGroup = item.title.toString() } viewModel.startOrStopSearch() viewModel.refresh() @@ -279,9 +272,16 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c tocAdapter.setItems(null) binding.clToc.visible() binding.loadingToc.show() - viewModel.getToc(searchBook, tocSuccess) { + val book = searchBook.toBook() + viewModel.getToc(book, { binding.clToc.gone() toastOnUi(it) + }) { toc: List, _: BookSource -> + tocAdapter.durChapterIndex = + BookHelp.getDurChapter(viewModel.chapterIndex, viewModel.chapterTitle, toc) + binding.loadingToc.hide() + tocAdapter.setItems(toc) + binding.recyclerViewToc.scrollToPosition(tocAdapter.durChapterIndex - 5) } } @@ -309,8 +309,8 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c override fun deleteSource(searchBook: SearchBook) { viewModel.del(searchBook) if (bookUrl == searchBook.bookUrl) { - viewModel.firstSourceOrNull(searchBook)?.let { - changeSource(it) + viewModel.autoChangeSource(callBack?.oldBook?.type) { book, toc, source -> + callBack?.changeTo(source, book, toc) } } } @@ -326,25 +326,12 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c } } - private fun changeSource(searchBook: SearchBook) { - try { - val book = searchBook.toBook() - book.upInfoFromOld(callBack?.oldBook) - val source = appDb.bookSourceDao.getBookSource(book.origin) - callBack?.changeTo(source!!, book) - searchBook.time = System.currentTimeMillis() - viewModel.updateSource(searchBook) - } catch (e: Exception) { - toastOnUi("换源失败\n${e.localizedMessage}") - } - } - /** * 更新分组菜单 */ private fun upGroupMenu() { val menu: Menu = binding.toolBar.menu - val selectedGroup = getPrefString("searchGroup") + val selectedGroup = AppConfig.searchGroup menu.removeGroup(R.id.source_group) val allItem = menu.add(R.id.source_group, Menu.NONE, Menu.NONE, R.string.all_source) var hasSelectedGroup = false @@ -388,7 +375,7 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c interface CallBack { val oldBook: Book? - fun changeTo(source: BookSource, book: Book) + fun changeTo(source: BookSource, book: Book, toc: List) fun replaceContent(content: String) } diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt index 68797fab4..a3ad2b0bc 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt @@ -5,10 +5,8 @@ import android.os.Bundle import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter -import io.legado.app.data.entities.SearchBook import io.legado.app.exception.NoStackTraceException import io.legado.app.model.webBook.WebBook -import java.util.concurrent.ConcurrentHashMap @Suppress("MemberVisibilityCanBePrivate") class ChangeChapterSourceViewModel(application: Application) : @@ -17,8 +15,6 @@ class ChangeChapterSourceViewModel(application: Application) : var chapterIndex: Int = 0 var chapterTitle: String = "" - private val tocMap = ConcurrentHashMap>() - override fun initData(arguments: Bundle?) { super.initData(arguments) arguments?.let { bundle -> @@ -29,31 +25,6 @@ class ChangeChapterSourceViewModel(application: Application) : } } - fun getToc( - searchBook: SearchBook, - success: (toc: List) -> Unit, - error: (msg: String) -> Unit - ) { - execute { - return@execute tocMap[searchBook.bookUrl] - ?: let { - val book = searchBook.toBook() - val source = appDb.bookSourceDao.getBookSource(book.origin) - ?: throw NoStackTraceException("书源不存在") - if (book.tocUrl.isEmpty()) { - WebBook.getBookInfoAwait(this, source, book) - } - val toc = WebBook.getChapterListAwait(this, source, book) - tocMap[book.bookUrl] = toc - toc - } - }.onSuccess { - success(it) - }.onError { - error(it.localizedMessage ?: "获取目录出错") - } - } - fun getContent( book: Book, chapter: BookChapter, diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt index eef1bb942..9cf8fa8f5 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt @@ -457,9 +457,8 @@ class BookInfoActivity : override val oldBook: Book? get() = viewModel.bookData.value - override fun changeTo(source: BookSource, book: Book) { - upLoading(true) - viewModel.changeTo(source, book) + override fun changeTo(source: BookSource, book: Book, toc: List) { + viewModel.changeTo(source, book, toc) } override fun coverChangeTo(coverUrl: String) { diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index 1ed56f4ac..2aa8b9277 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -14,7 +14,6 @@ import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource import io.legado.app.exception.NoStackTraceException import io.legado.app.help.BookHelp -import io.legado.app.help.ContentProcessor import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.BookCover import io.legado.app.model.ReadBook @@ -24,7 +23,6 @@ import io.legado.app.utils.postEvent import io.legado.app.utils.toastOnUi import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.ensureActive class BookInfoViewModel(application: Application) : BaseViewModel(application) { val bookData = MutableLiveData() @@ -107,12 +105,11 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { fun loadBookInfo( book: Book, canReName: Boolean = true, - scope: CoroutineScope = viewModelScope, - changeDruChapterIndex: ((chapters: List) -> Unit)? = null, + scope: CoroutineScope = viewModelScope ) { execute(scope) { if (book.isLocalBook()) { - loadChapter(book, scope, changeDruChapterIndex) + loadChapter(book, scope) } else { bookSource?.let { bookSource -> WebBook.getBookInfo(this, bookSource, book, canReName = canReName) @@ -121,7 +118,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { if (inBookshelf) { appDb.bookDao.update(book) } - loadChapter(it, scope, changeDruChapterIndex) + loadChapter(it, scope) }.onError { AppLog.put("获取数据信息失败\n${it.localizedMessage}", it) context.toastOnUi(R.string.error_get_book_info) @@ -136,8 +133,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { private fun loadChapter( book: Book, - scope: CoroutineScope = viewModelScope, - changeDruChapterIndex: ((chapters: List) -> Unit)? = null, + scope: CoroutineScope = viewModelScope ) { execute(scope) { if (book.isLocalBook()) { @@ -156,11 +152,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { appDb.bookChapterDao.delByBook(book.bookUrl) appDb.bookChapterDao.insert(*it.toTypedArray()) } - if (changeDruChapterIndex == null) { - chapterListData.postValue(it) - } else { - changeDruChapterIndex(it) - } + chapterListData.postValue(it) }.onError { chapterListData.postValue(emptyList()) AppLog.put("获取目录失败\n${it.localizedMessage}", it) @@ -184,58 +176,18 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { } } - fun changeTo(source: BookSource, newBook: Book) { + fun changeTo(source: BookSource, newBook: Book, toc: List) { changeSourceCoroutine?.cancel() changeSourceCoroutine = execute { - var oldTocSize: Int = newBook.totalChapterNum - if (inBookshelf) { - bookData.value?.let { - oldTocSize = it.totalChapterNum - it.changeTo(newBook) - } - } - bookData.postValue(newBook) bookSource = source - if (newBook.tocUrl.isEmpty()) { - loadBookInfo(newBook, false, this) { - ensureActive() - upChangeDurChapterIndex(newBook, oldTocSize, it) - } - } else { - loadChapter(newBook, this) { - ensureActive() - upChangeDurChapterIndex(newBook, oldTocSize, it) - } - } + bookData.value!!.changeTo(newBook, toc) + bookData.postValue(newBook) + chapterListData.postValue(toc) }.onFinally { postEvent(EventBus.SOURCE_CHANGED, newBook.bookUrl) } } - private fun upChangeDurChapterIndex( - book: Book, - oldTocSize: Int, - chapters: List - ) { - execute { - book.durChapterIndex = BookHelp.getDurChapter( - book.durChapterIndex, - book.durChapterTitle, - chapters, - oldTocSize - ) - book.durChapterTitle = chapters[book.durChapterIndex].getDisplayTitle( - ContentProcessor.get(book.name, book.origin).getTitleReplaceRules() - ) - if (inBookshelf) { - appDb.bookDao.update(book) - appDb.bookChapterDao.insert(*chapters.toTypedArray()) - } - bookData.postValue(book) - chapterListData.postValue(chapters) - } - } - fun topBook() { execute { bookData.value?.let { book -> @@ -300,7 +252,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { fun delBook(deleteOriginal: Boolean = false, success: (() -> Unit)? = null) { execute { bookData.value?.let { - Book.delete(it) + it.delete() inBookshelf = false if (it.isLocalBook()) { LocalBook.deleteBook(it, deleteOriginal) diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index 206ed2163..431b73029 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -14,6 +14,7 @@ import androidx.core.view.size import com.jaredrummler.android.colorpicker.ColorPickerDialogListener import io.legado.app.BuildConfig import io.legado.app.R +import io.legado.app.constant.BookType import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey import io.legado.app.constant.Status @@ -38,6 +39,8 @@ import io.legado.app.model.ReadBook import io.legado.app.receiver.TimeBatteryReceiver import io.legado.app.service.BaseReadAloudService import io.legado.app.ui.about.AppLogDialog +import io.legado.app.ui.book.audio.AudioPlayActivity +import io.legado.app.ui.book.bookmark.BookmarkDialog import io.legado.app.ui.book.changesource.ChangeBookSourceDialog import io.legado.app.ui.book.changesource.ChangeChapterSourceDialog import io.legado.app.ui.book.read.config.* @@ -51,7 +54,6 @@ import io.legado.app.ui.book.read.page.provider.TextPageFactory import io.legado.app.ui.book.searchContent.SearchContentActivity import io.legado.app.ui.book.searchContent.SearchResult import io.legado.app.ui.book.source.edit.BookSourceEditActivity -import io.legado.app.ui.book.toc.BookmarkDialog import io.legado.app.ui.book.toc.TocActivityResult import io.legado.app.ui.browser.WebViewActivity import io.legado.app.ui.dict.DictDialog @@ -715,8 +717,19 @@ class ReadBookActivity : BaseReadBookActivity(), override val oldBook: Book? get() = ReadBook.book - override fun changeTo(source: BookSource, book: Book) { - viewModel.changeTo(source, book) + override fun changeTo(source: BookSource, book: Book, toc: List) { + if (book.type != BookType.audio) { + viewModel.changeTo(source, book, toc) + } else { + ReadAloud.stop(this) + launch { + ReadBook.book?.changeTo(book, toc) + } + startActivity { + putExtra("bookUrl", book.bookUrl) + } + finish() + } } override fun replaceContent(content: String) { diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt index 80c233673..3293dba25 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt @@ -10,6 +10,7 @@ import io.legado.app.constant.AppLog import io.legado.app.constant.EventBus import io.legado.app.data.appDb import io.legado.app.data.entities.Book +import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookProgress import io.legado.app.data.entities.BookSource import io.legado.app.exception.NoStackTraceException @@ -30,7 +31,6 @@ import io.legado.app.utils.postEvent import io.legado.app.utils.toStringArray import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.ensureActive class ReadBookViewModel(application: Application) : BaseViewModel(application) { val permissionDenialLiveData = MutableLiveData() @@ -191,40 +191,22 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { /** * 换源 */ - fun changeTo(source: BookSource, book: Book) { + fun changeTo(source: BookSource, book: Book, toc: List) { changeSourceCoroutine?.cancel() changeSourceCoroutine = execute { ReadBook.upMsg(context.getString(R.string.loading)) - if (book.tocUrl.isEmpty()) { - WebBook.getBookInfoAwait(this, source, book) - } - ensureActive() - val chapters = WebBook.getChapterListAwait(this, source, book) - ensureActive() - val oldBook = ReadBook.book!! - book.durChapterIndex = BookHelp.getDurChapter( - oldBook.durChapterIndex, - oldBook.durChapterTitle, - chapters, - oldBook.totalChapterNum - ) - book.durChapterTitle = chapters[book.durChapterIndex].getDisplayTitle( - ContentProcessor.get(book.name, book.origin).getTitleReplaceRules() - ) - ensureActive() - val nextChapter = chapters.getOrElse(book.durChapterIndex) { - chapters.first() + ReadBook.book!!.changeTo(book, toc) + val nextChapter = toc.getOrElse(book.durChapterIndex) { + toc.first() } WebBook.getContentAwait( this, bookSource = source, book = book, - bookChapter = chapters[book.durChapterIndex], + bookChapter = toc[book.durChapterIndex], nextChapterUrl = nextChapter.url ) - ensureActive() - oldBook.changeTo(book) - appDb.bookChapterDao.insert(*chapters.toTypedArray()) + appDb.bookChapterDao.insert(*toc.toTypedArray()) ReadBook.resetData(book) ReadBook.upMsg(null) ReadBook.loadContent(resetPageOffset = true) @@ -244,10 +226,17 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { if (!AppConfig.autoChangeSource) return execute { val sources = appDb.bookSourceDao.allTextEnabled - WebBook.preciseSearchAwait(this, sources, name, author)?.let { - it.second.upInfoFromOld(ReadBook.book) - changeTo(it.first, it.second) - } ?: throw NoStackTraceException("自动换源失败") + sources.forEach { source -> + WebBook.preciseSearchAwait(this, source, name, author).getOrNull()?.let { book -> + if (book.tocUrl.isEmpty()) { + WebBook.getBookInfoAwait(this, source, book) + } + val toc = WebBook.getChapterListAwait(this, source, book) + changeTo(source, book, toc) + return@execute + } + } + throw NoStackTraceException("自动换源失败") }.onStart { ReadBook.upMsg(context.getString(R.string.source_auto_changing)) }.onError { @@ -272,7 +261,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { fun removeFromBookshelf(success: (() -> Unit)?) { execute { - Book.delete(ReadBook.book) + ReadBook.book?.delete() }.onSuccess { success?.invoke() } diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt index edd79ab82..bb6463608 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt @@ -22,6 +22,7 @@ import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.SearchKeyword import io.legado.app.databinding.ActivityBookSearchBinding +import io.legado.app.help.config.AppConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.* import io.legado.app.ui.book.info.BookInfoActivity @@ -66,14 +67,14 @@ class SearchActivity : VMBaseActivity() private val searchFinishCallback: (isEmpty: Boolean) -> Unit = { if (it) { - val searchGroup = getPrefString("searchGroup") - if (!searchGroup.isNullOrEmpty()) { + val searchGroup = AppConfig.searchGroup + if (searchGroup.isNotEmpty()) { launch { alert("搜索结果为空") { setMessage("${searchGroup}分组搜索结果为空,是否切换到全部分组") cancelButton() okButton { - putPrefString("searchGroup", "") + AppConfig.searchGroup = "" viewModel.searchKey = "" viewModel.search(searchView.query.toString()) } @@ -123,9 +124,9 @@ class SearchActivity : VMBaseActivity if (item.groupId == R.id.source_group) { item.isChecked = true if (item.title.toString() == getString(R.string.all_source)) { - putPrefString("searchGroup", "") + AppConfig.searchGroup = "" } else { - putPrefString("searchGroup", item.title.toString()) + AppConfig.searchGroup = item.title.toString() } searchView.query?.toString()?.trim()?.let { searchView.setQuery(it, true) @@ -280,7 +281,7 @@ class SearchActivity : VMBaseActivity - val selectedGroup = getPrefString("searchGroup") + val selectedGroup = AppConfig.searchGroup menu.removeGroup(R.id.source_group) val allItem = menu.add(R.id.source_group, Menu.NONE, Menu.NONE, R.string.all_source) var hasSelectedGroup = false diff --git a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt index 059e91a90..3bf1e3562 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt @@ -86,14 +86,12 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat text.isJsonArray() -> { val items: List> = jsonPath.parse(text).read("$") val jsonItem = jsonPath.parse(items[0]) - BookSource.fromJson(jsonItem.jsonString()) + BookSource.fromJson(jsonItem.jsonString()).getOrThrow() } text.isJsonObject() -> { - BookSource.fromJson(text) - } - else -> { - null + BookSource.fromJson(text).getOrThrow() } + else -> throw NoStackTraceException("格式不对") } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 19b473a02..05b8d5000 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -230,10 +230,10 @@ class BookSourceActivity : VMBaseActivity { val key = searchKey.substringAfter("group:") - appDb.bookSourceDao.flowGroupSearch("%$key%") + appDb.bookSourceDao.flowGroupSearch(key) } else -> { - appDb.bookSourceDao.flowSearch("%$searchKey%") + appDb.bookSourceDao.flowSearch(searchKey) } }.conflate().map { data -> if (sortAscending) when (sort) { diff --git a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt b/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt index 84d0c011f..b9a9fb893 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt @@ -6,6 +6,7 @@ import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.data.entities.Bookmark import io.legado.app.databinding.ItemBookmarkBinding +import io.legado.app.utils.gone import splitties.views.onLongClick class BookmarkAdapter(context: Context, val callback: Callback) : @@ -22,7 +23,9 @@ class BookmarkAdapter(context: Context, val callback: Callback) : payloads: MutableList ) { binding.tvChapterName.text = item.chapterName + binding.tvBookText.gone(item.bookText.isEmpty()) binding.tvBookText.text = item.bookText + binding.tvContent.gone(item.content.isEmpty()) binding.tvContent.text = item.content } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkFragment.kt b/app/src/main/java/io/legado/app/ui/book/toc/BookmarkFragment.kt index b0ec07f3b..8bcf03930 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkFragment.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/BookmarkFragment.kt @@ -11,6 +11,7 @@ import io.legado.app.data.appDb import io.legado.app.data.entities.Bookmark import io.legado.app.databinding.FragmentBookmarkBinding import io.legado.app.lib.theme.primaryColor +import io.legado.app.ui.book.bookmark.BookmarkDialog import io.legado.app.ui.widget.recycler.UpLinearLayoutManager import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.setEdgeEffectColor diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt index 7eec1a6fb..7e5f3d823 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt @@ -22,6 +22,7 @@ import io.legado.app.databinding.ActivityMainBinding import io.legado.app.help.BookHelp import io.legado.app.help.config.AppConfig import io.legado.app.help.config.LocalConfig +import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.storage.Backup import io.legado.app.lib.theme.elevation import io.legado.app.lib.theme.primaryColor @@ -175,7 +176,9 @@ class MainActivity : VMBaseActivity(), override fun onDestroy() { super.onDestroy() - BookHelp.clearRemovedCache() + Coroutine.async { + BookHelp.clearInvalidCache() + } } override fun observeLiveBus() { diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt index 3f7b8f720..43fddca9d 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt @@ -132,7 +132,7 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application) if (name.isNotEmpty() && appDb.bookDao.getBook(name, author) == null) { WebBook.preciseSearch(this, bookSources, name, author) .onSuccess { - val book = it.second + val book = it.first if (groupId > 0) { book.group = groupId } diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt index 8e2b1e049..42c374329 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt @@ -123,10 +123,10 @@ class ExploreFragment : VMBaseFragment(R.layout.fragment_explo } searchKey.startsWith("group:") -> { val key = searchKey.substringAfter("group:") - appDb.bookSourceDao.flowGroupExplore("%$key%") + appDb.bookSourceDao.flowGroupExplore(key) } else -> { - appDb.bookSourceDao.flowExplore("%$searchKey%") + appDb.bookSourceDao.flowExplore(searchKey) } }.catch { AppLog.put("发现界面更新数据出错", it) diff --git a/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt b/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt index e4464a17c..92c31c288 100644 --- a/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt @@ -20,6 +20,7 @@ import io.legado.app.service.WebService import io.legado.app.ui.about.AboutActivity import io.legado.app.ui.about.DonateActivity import io.legado.app.ui.about.ReadRecordActivity +import io.legado.app.ui.book.bookmark.AllBookmarkActivity import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.ui.config.ConfigActivity import io.legado.app.ui.config.ConfigTag @@ -135,6 +136,7 @@ class MyFragment : BaseFragment(R.layout.fragment_my_config) { when (preference.key) { "bookSourceManage" -> startActivity() "replaceManage" -> startActivity() + "bookmark" -> startActivity() "setting" -> startActivity { putExtra("configTag", ConfigTag.OTHER_CONFIG) } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt index 75634c2a1..25002eb3a 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt @@ -52,7 +52,7 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati execute(context = Dispatchers.Main) { var source: RssSource? = null context.getClipText()?.let { json -> - source = RssSource.fromJson(json) + source = RssSource.fromJson(json).getOrThrow() } source }.onError { @@ -69,7 +69,7 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati fun importSource(text: String, finally: (source: RssSource) -> Unit) { execute { val text1 = text.trim() - RssSource.fromJson(text1)?.let { + RssSource.fromJson(text1).getOrThrow().let { finally.invoke(it) } }.onError { diff --git a/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt b/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt index 3aa2b95c1..6f83d03aa 100644 --- a/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt +++ b/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt @@ -6,23 +6,36 @@ import androidx.compose.material.lightColors import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import io.legado.app.help.config.ThemeConfig +import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.primaryColor +import io.legado.app.utils.ColorUtils import splitties.init.appCtx +object AppTheme { + + val colors + get() = if (ThemeConfig.isDarkTheme()) { + darkColors( + primary = Color(appCtx.accentColor), + primaryVariant = Color(ColorUtils.darkenColor(appCtx.accentColor)), + secondary = Color(appCtx.primaryColor), + secondaryVariant = Color(appCtx.primaryColor) + ) + } else { + lightColors( + primary = Color(appCtx.accentColor), + primaryVariant = Color(ColorUtils.darkenColor(appCtx.accentColor)), + secondary = Color(appCtx.primaryColor), + secondaryVariant = Color(appCtx.primaryColor) + ) + } + +} @Composable fun AppTheme(content: @Composable () -> Unit) { - val colors = if (ThemeConfig.isDarkTheme()) { - darkColors( - primary = Color(appCtx.primaryColor), - ) - } else { - lightColors( - primary = Color(appCtx.primaryColor), - ) - } MaterialTheme( - colors = colors, + colors = AppTheme.colors, content = content ) } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt b/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt index 57936ad0d..d7e50a0be 100644 --- a/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt @@ -98,6 +98,11 @@ class SelectActionBar @JvmOverloads constructor( btnRevertSelection.isClickable = isClickable btnSelectActionMain.isEnabled = isClickable btnSelectActionMain.isClickable = isClickable + if (isClickable) { + ivMenuMore.setColorFilter(context.primaryTextColor) + } else { + ivMenuMore.setColorFilter(context.secondaryTextColor) + } ivMenuMore.isEnabled = isClickable ivMenuMore.isClickable = isClickable } diff --git a/app/src/main/java/io/legado/app/utils/GsonExtensions.kt b/app/src/main/java/io/legado/app/utils/GsonExtensions.kt index 443b95560..9329613e3 100644 --- a/app/src/main/java/io/legado/app/utils/GsonExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/GsonExtensions.kt @@ -4,6 +4,8 @@ import com.google.gson.* import com.google.gson.internal.LinkedTreeMap import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonWriter +import java.io.InputStream +import java.io.InputStreamReader import java.io.OutputStream import java.io.OutputStreamWriter import java.lang.reflect.ParameterizedType @@ -37,6 +39,20 @@ inline fun Gson.fromJsonArray(json: String?): Result?> { } } +inline fun Gson.fromJsonObject(inputStream: InputStream?): Result { + return kotlin.runCatching { + val reader = InputStreamReader(inputStream) + fromJson(reader, genericType()) as? T + } +} + +inline fun Gson.fromJsonArray(inputStream: InputStream?): Result?> { + return kotlin.runCatching { + val reader = InputStreamReader(inputStream) + fromJson(reader, ParameterizedTypeImpl(T::class.java)) as? List + } +} + fun Gson.writeToOutputStream(out: OutputStream, any: Any) { val writer = JsonWriter(OutputStreamWriter(out, "UTF-8")) writer.setIndent(" ") diff --git a/app/src/main/java/io/legado/app/utils/ViewExtensions.kt b/app/src/main/java/io/legado/app/utils/ViewExtensions.kt index a28ba8472..acd723022 100644 --- a/app/src/main/java/io/legado/app/utils/ViewExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/ViewExtensions.kt @@ -98,6 +98,14 @@ fun View.gone() { } } +fun View.gone(gone: Boolean) { + if (gone) { + gone() + } else { + visibility = VISIBLE + } +} + fun View.invisible() { if (visibility != INVISIBLE) { visibility = INVISIBLE diff --git a/app/src/main/res/layout/activity_all_bookmark.xml b/app/src/main/res/layout/activity_all_bookmark.xml new file mode 100644 index 000000000..614f5baf6 --- /dev/null +++ b/app/src/main/res/layout/activity_all_bookmark.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_arrange_book.xml b/app/src/main/res/layout/activity_arrange_book.xml index 1be7bdb41..e85718977 100644 --- a/app/src/main/res/layout/activity_arrange_book.xml +++ b/app/src/main/res/layout/activity_arrange_book.xml @@ -1,5 +1,5 @@ - + app:title="@string/arrange_bookshelf" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toBottomOf="@id/title_bar" + app:layout_constraintBottom_toTopOf="@id/select_action_bar" /> + android:layout_height="wrap_content" + app:layout_constraintBottom_toBottomOf="parent" /> + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ecd80ee3d..92ac73aee 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -18,6 +18,7 @@ android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/background" + app:itemActiveIndicatorStyle="@color/transparent" app:labelVisibilityMode="unlabeled" app:menu="@menu/main_bnv" /> diff --git a/app/src/main/res/layout/dialog_source_picker.xml b/app/src/main/res/layout/dialog_source_picker.xml new file mode 100644 index 000000000..4b0818ebd --- /dev/null +++ b/app/src/main/res/layout/dialog_source_picker.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_text_view.xml b/app/src/main/res/layout/dialog_text_view.xml index df50b0e81..8688aa703 100644 --- a/app/src/main/res/layout/dialog_text_view.xml +++ b/app/src/main/res/layout/dialog_text_view.xml @@ -10,6 +10,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:padding="12dp" + android:textColor="@color/secondaryText" android:textIsSelectable="true" /> + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_1line_text_and_del.xml b/app/src/main/res/layout/item_1line_text_and_del.xml index 2cc6daa2c..b65a0b09b 100644 --- a/app/src/main/res/layout/item_1line_text_and_del.xml +++ b/app/src/main/res/layout/item_1line_text_and_del.xml @@ -14,6 +14,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" + android:background="?attr/selectableItemBackground" android:singleLine="true" android:textColor="@color/primaryText" /> diff --git a/app/src/main/res/layout/view_tab_layout.xml b/app/src/main/res/layout/view_tab_layout.xml index 5efc6cd26..68c732261 100644 --- a/app/src/main/res/layout/view_tab_layout.xml +++ b/app/src/main/res/layout/view_tab_layout.xml @@ -4,6 +4,7 @@ android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@android:color/transparent" app:tabBackground="@android:color/transparent" app:tabRippleColor="@android:color/transparent" android:theme="?attr/actionBarStyle" /> \ No newline at end of file diff --git a/app/src/main/res/layout/view_tab_layout_min.xml b/app/src/main/res/layout/view_tab_layout_min.xml index badf89a01..4033442d5 100644 --- a/app/src/main/res/layout/view_tab_layout_min.xml +++ b/app/src/main/res/layout/view_tab_layout_min.xml @@ -5,6 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:theme="?attr/actionBarStyle" + android:background="@android:color/transparent" app:tabBackground="@android:color/transparent" app:tabRippleColor="@android:color/transparent" app:tabMaxWidth="100dp" diff --git a/app/src/main/res/menu/arrange_book_sel.xml b/app/src/main/res/menu/arrange_book_sel.xml index 880569d40..887f91524 100644 --- a/app/src/main/res/menu/arrange_book_sel.xml +++ b/app/src/main/res/menu/arrange_book_sel.xml @@ -17,4 +17,8 @@ android:id="@+id/menu_add_to_group" android:title="@string/add_to_group" /> + + \ No newline at end of file diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 9143354c7..044b7b5d6 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -776,8 +776,8 @@ Cambiar tema predeterminado Ordenar por hora de actualización Contenido de búsqueda - ¡Siga [开源阅读] en WeChat para obtener más feeds RSS! - Actualmente no hay una fuente para Descubrir, siga el número público [开源 阅读] para agregar una fuente de libro a través de Descubrir. + Empty now! + Actualmente no hay una fuente para Descubrir! 将焦点放到输入框按下物理按键会自动录入键值,多个按键会自动用英文逗号隔开. Nombre del tema Limpiar automáticamente los datos de búsqueda caducados @@ -965,5 +965,9 @@ 系统tts设置 打开系统tts设置界面 非播放状态无法定时 + 所有书签 + 批量换源 + 书籍类型不一样 + 是否确认换源 diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index ab67846fc..dfb209873 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -46,7 +46,7 @@ Recent reading Last reading What\'s new - The bookshelf is still empty. Search for books or add them from discovery! \n if you use it for the first time, please pay attention to the public account [开源阅读] to get the book source! + The bookshelf is still empty. Search for books or add them from discovery! \n if you use it for the first time, please open legado.top get help! Search Download List @@ -779,8 +779,8 @@ Switch default theme Sort by update time Search content - Follow Wechat official account [开源阅读] to get Subscription source - Empty now,Follow Wechat official account [开源阅读] to get Discovery source + Empty now! + Empty now! 将焦点放到输入框按下物理按键会自动录入键值,多个按键会自动用英文逗号隔开. Theme name "Clear expired search histories automatically " @@ -968,5 +968,9 @@ 系统tts设置 打开系统tts设置界面 非播放状态无法定时 + 所有书签 + 批量换源 + 书籍类型不一样 + 是否确认换源 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index fcd5e4613..ac7d406b6 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -46,7 +46,7 @@ Leitura recente Última leitura Novidades - A estante está vazia. Procure por livros ou adicione-os via descoberta! \n se você o usa pela primeira vez, por favor, preste atenção à conta pública [开源阅读] para obter a fonte do livro! + A estante está vazia. Procure por livros ou adicione-os via descoberta! Pesquisar Download Lista @@ -777,8 +777,8 @@ Alterar o tema padrão Ordenar por tempo de atualização Pesquisar conteúdo - Siga [开源阅读] no WeChat para mais fontes de RSS! - Atualmente não há nenhuma fonte, siga o número público [开源阅读] para adicionar uma fonte de livro via Descoberta + Empty now! + Atualmente não há nenhuma fonte! 将焦点放到输入框按下物理按键会自动录入键值,多个按键会自动用英文逗号隔开. Nome de tema Excluir automaticamente dados vencidos da busca @@ -968,5 +968,9 @@ 系统tts设置 打开系统tts设置界面 非播放状态无法定时 + 所有书签 + 批量换源 + 书籍类型不一样 + 是否确认换源 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 7be8fcc22..56dab2441 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -43,7 +43,7 @@ 最近閲讀 最後閲讀 更新日誌 - 書架還空著,先去搜索書籍或從發現裏添加吧!\n如果初次使用請先關註公眾號[开源阅读]獲取書源! + 書架還空著,先去搜索書籍或從發現裏添加吧! 搜尋 下載 列表 @@ -775,8 +775,8 @@ 分享選中源 更新時間排序 全文搜索 - 關注公眾號[开源阅读]獲取訂閲源! - 目前沒有發現源,關注公眾號[开源阅读]添加包含發現的書源! + Empty now! + 目前沒有發現源! 將焦點放到輸入框按下物理按鍵會自動輸入鍵值,多個按鍵會自動用英文逗號隔開. 主題名 自動清除過期搜尋資料 @@ -965,5 +965,9 @@ 系统tts设置 打开系统tts设置界面 非播放状态无法定时 + 所有书签 + 批量换源 + 书籍类型不一样 + 是否确认换源 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index dabf42176..69805157e 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -45,7 +45,7 @@ 最近閱讀 最後閱讀 更新日誌 - 書架還空著,先去搜尋書籍或從發現裡添加吧!\n如果初次使用請先關注公眾號[开源阅读]獲取書源! + 書架還空著,先去搜尋書籍或從發現裡添加吧! 搜尋 下載 列表 @@ -778,8 +778,8 @@ 切換預設主題 更新時間排序 全文搜尋 - 關注公眾號[开源阅读]獲取訂閱源! - 目前沒有發現源,關注公眾號[开源阅读]添加包含發現的書源! + Empty now! + 目前沒有發現源! 將焦點放到輸入框按下物理按鍵會自動輸入鍵值,多個按鍵會自動用英文逗號隔開. 主題名稱 自動清除過期搜尋資料 @@ -967,5 +967,9 @@ 系统tts设置 打开系统tts设置界面 非播放状态无法定时 + 所有书签 + 批量换源 + 书籍类型不一样 + 是否确认换源 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index ee43e4273..8f9c01346 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -45,7 +45,7 @@ 最近阅读 最后阅读 更新日志 - 书架还空着,先去搜索书籍或从发现里添加吧!\n初次使用请关注公众号[开源阅读]获取书源和教程! + 书架还空着,先去搜索书籍或从发现里添加吧! 搜索 下载 列表 @@ -780,8 +780,8 @@ 全文搜索 搜索结果 搜索结果为空 - 关注公众号[开源阅读]获取订阅源! - 当前没有发现源,关注公众号[开源阅读]添加带发现的书源! + Empty now! + 当前没有发现源! 将焦点放到输入框按下物理按键会自动录入键值,多个按键会自动用英文逗号隔开. 主题名称 自动清除过期搜索数据 @@ -967,5 +967,9 @@ 系统tts设置 打开系统tts设置界面 非播放状态无法定时 + 所有书签 + 批量换源 + 书籍类型不一样 + 是否确认换源 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8ad3e0b0a..9423a4cf5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,7 +46,7 @@ Recent reading Last reading What\'s new - The bookshelf is still empty. Search for books or add them from discovery! \n if you use it for the first time, please pay attention to the public account [开源阅读] to get the book source! + The bookshelf is still empty. Search for books or add them from discovery! Search Download List @@ -780,8 +780,8 @@ Sort by update time Sort by respond time Search content - Follow Wechat official account [开源阅读] to get Subscription source - Empty now,Follow Wechat official account [开源阅读] to get Discovery source + Empty now! + Empty now! 将焦点放到输入框按下物理按键会自动录入键值,多个按键会自动用英文逗号隔开. Theme name "Clear expired search histories automatically " @@ -968,5 +968,9 @@ 系统tts设置 打开系统tts设置界面 非播放状态无法定时 + 所有书签 + 批量换源 + 书籍类型不一样 + 是否确认换源 diff --git a/app/src/main/res/xml/pref_main.xml b/app/src/main/res/xml/pref_main.xml index e4e3d3cee..45cba0157 100644 --- a/app/src/main/res/xml/pref_main.xml +++ b/app/src/main/res/xml/pref_main.xml @@ -76,6 +76,13 @@ app:iconSpaceReserved="false" app:layout="@layout/view_preference_category"> + +