├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── qc │ │ └── mycomic │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 6.jpg │ │ └── litepal.xml │ ├── java │ │ └── com │ │ │ └── qc │ │ │ └── common │ │ │ ├── constant │ │ │ ├── AppConstant.java │ │ │ ├── Constant.java │ │ │ └── TmpData.java │ │ │ ├── en │ │ │ └── SettingEnum.java │ │ │ ├── self │ │ │ ├── CommonData.java │ │ │ ├── GsyPlayer.java │ │ │ ├── ImageConfig.java │ │ │ ├── ScrollSpeedLinearLayoutManger.java │ │ │ └── SnapImageInfo.java │ │ │ ├── ui │ │ │ ├── activity │ │ │ │ ├── BaseGsyVideoActivity.java │ │ │ │ ├── GsyVideoActivity.java │ │ │ │ ├── LauncherActivity.java │ │ │ │ └── MainActivity.java │ │ │ ├── adapter │ │ │ │ ├── ChapterAdapter.java │ │ │ │ ├── ChapterItemAdapter.java │ │ │ │ ├── ComicReaderAdapter.java │ │ │ │ ├── NovelReaderAdapter.java │ │ │ │ ├── RankAdapter.java │ │ │ │ ├── RankLeftAdapter.java │ │ │ │ ├── ReaderListAdapter.java │ │ │ │ ├── SearchAdapter.java │ │ │ │ └── ShelfAdapter.java │ │ │ ├── fragment │ │ │ │ ├── BaseReaderFragment.java │ │ │ │ ├── ChapterFragment.java │ │ │ │ ├── ChapterItemFragment.java │ │ │ │ ├── ComicReaderFragment.java │ │ │ │ ├── MyHomeFragment.java │ │ │ │ ├── NovelReaderFragment.java │ │ │ │ ├── PersonFragment.java │ │ │ │ ├── PersonReaderFragment.java │ │ │ │ ├── PersonSourceFragment.java │ │ │ │ ├── RankFragment.java │ │ │ │ ├── ReaderDetailFragment.java │ │ │ │ ├── SearchBaseFragment.java │ │ │ │ ├── SearchFragment.java │ │ │ │ ├── SearchResultFragment.java │ │ │ │ ├── ShelfFragment.java │ │ │ │ └── ShelfItemFragment.java │ │ │ ├── presenter │ │ │ │ ├── ChapterPresenter.java │ │ │ │ ├── RankPresenter.java │ │ │ │ ├── ReaderPresenter.java │ │ │ │ ├── SearchPresenter.java │ │ │ │ ├── ShelfPresenter.java │ │ │ │ └── UpdatePresenter.java │ │ │ └── view │ │ │ │ ├── ChapterView.java │ │ │ │ ├── RankView.java │ │ │ │ ├── ReaderView.java │ │ │ │ ├── SearchView.java │ │ │ │ ├── ShelfView.java │ │ │ │ └── UpdateView.java │ │ │ └── util │ │ │ ├── AnimationUtil.java │ │ │ ├── DBUtil.java │ │ │ ├── EntityHelper.java │ │ │ ├── EntityUtil.java │ │ │ ├── ImgUtil.java │ │ │ ├── PermissionUtil.java │ │ │ ├── PopupUtil.java │ │ │ ├── RestartUtil.java │ │ │ ├── SettingItemUtil.java │ │ │ ├── SettingUtil.java │ │ │ └── VersionUtil.java │ └── res │ │ ├── drawable │ │ ├── bg_image.xml │ │ ├── head.jpg │ │ ├── ic_baseline_brightness_1_24.xml │ │ ├── ic_baseline_brightness_2_24.xml │ │ ├── ic_baseline_check_circle_24.xml │ │ ├── ic_baseline_favorite_24.xml │ │ ├── ic_baseline_favorite_border_24.xml │ │ ├── ic_baseline_home_24.xml │ │ ├── ic_baseline_home_select_24.xml │ │ ├── ic_baseline_image_24.xml │ │ ├── ic_baseline_image_search_24.xml │ │ ├── ic_baseline_keyboard_arrow_left_24.xml │ │ ├── ic_baseline_keyboard_arrow_right_24.xml │ │ ├── ic_baseline_list_24.xml │ │ ├── ic_baseline_menu_24.xml │ │ ├── ic_baseline_person_24.xml │ │ ├── ic_baseline_person_select_24.xml │ │ ├── ic_baseline_search_24.xml │ │ ├── ic_baseline_search_select_24.xml │ │ ├── ic_baseline_settings_24.xml │ │ ├── ic_baseline_swap_vert_24.xml │ │ ├── ic_baseline_turned_in_24.xml │ │ ├── ic_image_background.xml │ │ ├── ic_image_error_24.xml │ │ ├── ic_image_none.png │ │ ├── ic_image_reader_background.xml │ │ ├── ic_image_reader_error_foreground.xml │ │ ├── ic_image_reader_loading_foreground.xml │ │ ├── ic_image_shelf_error_foreground.xml │ │ ├── ic_image_shelf_loading_foreground.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_text.png │ │ ├── ic_text_black.png │ │ ├── ic_text_blue.png │ │ └── splash.xml │ │ ├── layout │ │ ├── activity_launcher.xml │ │ ├── activity_main.xml │ │ ├── activity_video.xml │ │ ├── fragment_chapter.xml │ │ ├── fragment_dark.xml │ │ ├── fragment_person.xml │ │ ├── fragment_rank_left.xml │ │ ├── fragment_reader_bottom.xml │ │ ├── fragment_reader_display.xml │ │ ├── fragment_reader_list.xml │ │ ├── fragment_reader_settings.xml │ │ ├── fragment_reader_settings_novel.xml │ │ ├── fragment_search.xml │ │ ├── fragment_search_result.xml │ │ ├── fragment_shelf.xml │ │ ├── fragment_shelf_collect.xml │ │ ├── fragment_shelf_history.xml │ │ ├── fragment_test.xml │ │ ├── fragment_web.xml │ │ ├── item_chapter.xml │ │ ├── item_rank_left.xml │ │ ├── item_rank_right.xml │ │ ├── item_rank_right_simple.xml │ │ ├── item_reader.xml │ │ ├── item_reader_list.xml │ │ ├── item_reader_novel.xml │ │ ├── item_search.xml │ │ ├── item_shelf.xml │ │ ├── layout.xml │ │ ├── left_rank.xml │ │ ├── module_image_progress.xml │ │ ├── module_image_reader.xml │ │ ├── module_image_shelf.xml │ │ ├── top_person.xml │ │ ├── video_player_gsy.xml │ │ ├── view_border.xml │ │ └── viewpager_chapter.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── network_security_config.xml │ └── test │ └── java │ └── com │ └── qc │ └── mycomic │ └── ExampleUnitTest.java ├── build.gradle ├── common ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── libs-build │ ├── fastjson-1.2.75.jar │ ├── kotlin-stdlib-1.3.72.jar │ ├── litepal-core-3.0.0.jar │ ├── okhttp-3.14.4.jar │ ├── okio-2.5.0.jar │ └── rhino-1.7.13.jar ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── top │ │ └── luqichuang │ │ ├── common │ │ ├── en │ │ │ ├── NSourceEnum.java │ │ │ ├── SourceEnum.java │ │ │ └── VSourceEnum.java │ │ ├── json │ │ │ ├── JsonNode.java │ │ │ └── JsonStarter.java │ │ ├── jsoup │ │ │ ├── JsoupNode.java │ │ │ └── JsoupStarter.java │ │ ├── model │ │ │ ├── ChapterInfo.java │ │ │ ├── Content.java │ │ │ ├── Entity.java │ │ │ ├── EntityInfo.java │ │ │ └── Source.java │ │ ├── self │ │ │ └── CommonCallback.java │ │ ├── tst │ │ │ ├── BaseComicTest.java │ │ │ ├── BaseNovelTest.java │ │ │ ├── BaseSourceTest.java │ │ │ └── BaseVideoTest.java │ │ └── util │ │ │ ├── DateUtil.java │ │ │ ├── DecryptUtil.java │ │ │ ├── FileUtil.java │ │ │ ├── MapUtil.java │ │ │ ├── NetUtil.java │ │ │ ├── SourceHelper.java │ │ │ ├── SourceUtil.java │ │ │ └── StringUtil.java │ │ ├── mycomic │ │ ├── model │ │ │ ├── BaseComicSource.java │ │ │ ├── Comic.java │ │ │ └── ComicInfo.java │ │ └── source │ │ │ ├── AiYouMan.java │ │ │ ├── BL.java │ │ │ ├── BaoZi.java │ │ │ ├── BiliBili.java │ │ │ ├── DaShu.java │ │ │ ├── Du.java │ │ │ ├── MH118.java │ │ │ ├── MH118W.java │ │ │ ├── MH1234.java │ │ │ ├── ManHuaFen.java │ │ │ ├── ManHuaTai.java │ │ │ ├── MiTui.java │ │ │ ├── OH.java │ │ │ ├── PuFei.java │ │ │ ├── QiMiao.java │ │ │ ├── SiSi.java │ │ │ └── TengXun.java │ │ ├── mynovel │ │ ├── model │ │ │ ├── BaseNovelSource.java │ │ │ ├── Novel.java │ │ │ └── NovelInfo.java │ │ └── source │ │ │ ├── AiYue.java │ │ │ ├── K17.java │ │ │ ├── MiKanShu.java │ │ │ ├── MoYuan.java │ │ │ ├── QuanShu.java │ │ │ ├── QuanXiaoShuo.java │ │ │ ├── ShuBen.java │ │ │ ├── TaDu.java │ │ │ ├── XiaoShuoE.java │ │ │ ├── XinBiQuGe.java │ │ │ ├── XinBiQuGe2.java │ │ │ └── XuanShu.java │ │ └── myvideo │ │ ├── model │ │ ├── BaseVideoSource.java │ │ ├── Video.java │ │ └── VideoInfo.java │ │ └── source │ │ ├── AiYun.java │ │ ├── BiliBili.java │ │ ├── FengChe.java │ │ ├── FengChe2.java │ │ ├── MiLiMiLi.java │ │ ├── YingHua.java │ │ └── YingHua2.java │ └── test │ └── java │ └── top │ └── luqichuang │ └── common │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | /app/release/ 16 | /.idea/ 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyComic 2 | 3 | #### 介绍 4 | - **重要通知:v1.7.4之后的版本将不再更新代码,软件正常更新维护。** 5 | 6 | - MyComic安卓在线漫画阅读器,包含多个源网站资源,支持搜索收藏等功能,用过的都说好! 7 | 8 | - 前往下载最新Apk【[软件发布页面](https://gitee.com/luqichuang/MyComic/releases "Gitee地址")】( 9 | 下载最新的.apk后缀的文件,最终下载文件应为.apk后缀,如果使用手机Chrome浏览器或其他方式下载得到.apk.zip文件时请不要解压,手动删除.zip后缀即可,也可以换一个浏览器下载) 10 | 11 | - 欢迎加Q群 **741032316** ,群内不时更新最新Apk,更新计划等内容。关于软件的疑问或者建议都可以在群内畅聊! 12 | 13 |
14 | Q群二维码 15 |
16 | 17 | - 前排提示:收费漫画源(如腾讯、哔哩哔哩)仅获取其中的免费部分,因此会有缺页等情况,可换源观看对应漫画。 18 | 19 | #### 软件架构 20 | 21 | 1. [Tencent / QMUI_Android](https://github.com/Tencent/QMUI_Android "Tencent / QMUI_Android") : 腾讯UI框架。 22 | 2. [Theone / TheBaseAndroid](https://gitee.com/theoneee/TheBase "Theone / TheBaseAndroid") : 主要以QMUI封装的一个快速开发框架。 23 | 24 | #### 软件预览 25 | 26 | | 画架页面 | 详情页面 | 阅读页面 | 27 | |:--------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------:| 28 | | 搜索页面 | 个人中心 | 小说阅读页面 | 29 | 30 | #### 使用说明 31 | 32 | 1. 画架页可以检查漫画更新、长按漫画可以执行切换漫画源、查看详情、删除等操作。 33 | 2. 详情页可以切换漫画源、阅读最新章节、继续阅读等。 34 | 3. 阅读页面长按加载失败图片可以重新加载,长按已显示图片可以单独缩放。 35 | 4. 个人中心可以检查更新,获得最新软件。 36 | 5. 前往下载[最新APK](https://gitee.com/luqichuang/MyComic/releases "Gitee地址"):[Gitee](https://gitee.com/luqichuang/MyComic/releases "Gitee地址")、[GitHub](https://github.com/LC184722/MyComic/releases "GitHub地址")。 37 | 38 | #### 添加数据源方法 39 | 40 | 1. 数据源接口文件:common/src/main/java/top/luqichuang/common/model/Source.java,根据不同数据源分为BaseComicSource、BaseNovelSource、BaseVideoSource三个主要父类。 41 | 2. 以添加漫画源为例: 42 | - 在common/src/main/java/top/luqichuang/mycomic/source文件夹下创建文件并继承BaseComicSource类。 43 | - 实现或重写方法(可参考common/src/main/java/top/luqichuang/mycomic/source/BaoZi.java文件)。 44 | - 在common/src/main/java/top/luqichuang/common/en/CSourceEnum.java文件中添加对应枚举。 45 | 46 | #### 测试数据源方法 47 | 48 | 1. 测试文件父类:common/src/main/java/top/luqichuang/common/tst/BaseSourceTest.java。 49 | 2. 以测试漫画源为例: 50 | - 测试文件:common/src/test/java/top/luqichuang/common/ComicTest.java。 51 | - 解开对应方法注释即可进行测试。 52 | 53 | #### 数据源 54 | 55 | - ##### 漫画 56 | 57 | ``` 58 | 1. 米推漫画 59 | 2. 漫画粉[失效] 60 | 3. 扑飞漫画[失效] 61 | 4. 腾讯动漫 62 | 5. 哔哩哔哩漫画 63 | 6. OH漫画[失效] 64 | 7. 漫画台 65 | 8. 118漫画[失效] 66 | 9. 独漫画[失效] 67 | 10. BL漫画[失效] 68 | 11. 爱优漫 69 | 12. 1234漫画[失效] 70 | 13. 118漫画2[失效] 71 | 14. 奇妙漫画[失效] 72 | 15. 大树漫画[失效] 73 | 16. 思思漫画[失效] 74 | 17. 包子漫画 75 | 18. 七夕漫画 76 | 19. 酷漫屋 77 | 20. 好漫6[失效] 78 | 21. 都市漫画 79 | 22. 前未漫画[失效] 80 | 23. 品悦漫画 81 | 24. 来漫画 82 | 25. 6漫画 83 | 26. 160漫画 84 | ``` 85 | 86 | - ##### 小说 87 | 88 | ``` 89 | 1. 新笔趣阁 90 | 2. 全书网[失效] 91 | 3. 全小说[失效] 92 | 4. 爱阅小说 93 | 5. 炫书网 94 | 6. 17K小说 95 | 7. E小说 96 | 8. 墨缘文学[失效] 97 | 9. Mi看书[失效] 98 | 10. 新笔趣阁2 99 | 11. 书本网[失效] 100 | 12. 塔读文学 101 | ``` 102 | 103 | - ##### 番剧 104 | 105 | ``` 106 | 1. 樱花动漫[失效] 107 | 2. 米粒米粒[失效] 108 | 3. 风车动漫[失效] 109 | 4. 樱花动漫2[失效] 110 | 5. 哔哩哔哩 111 | 6. 风车动漫2 112 | 7. 爱云影视 113 | ``` 114 | 115 | #### 参与贡献 116 | 117 | 1. Fork 本仓库 118 | 2. 新建 Feat_xxx 分支 119 | 3. 提交代码 120 | 4. 新建 Pull Request 121 | 122 | #### 其他 123 | 124 | 1. 本项目仅供学习使用 125 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | static def gitVersionCode() { 4 | def cmd = 'git rev-list HEAD --first-parent --count' 5 | if (cmd.execute().text != '') { 6 | return cmd.execute().text.trim().toInteger() 7 | } else { 8 | return 100 9 | } 10 | } 11 | 12 | static def gitVersionTag() { 13 | def cmd = 'git describe --tags' 14 | def version = cmd.execute().text.trim() 15 | 16 | // def pattern = "-(\\d+)-g" 17 | // def matcher = version =~ pattern 18 | 19 | // if (matcher) { 20 | // version = version.substring(0, matcher.start()) + "." + matcher[0][1] 21 | // } else { 22 | // version = version + ".0" 23 | // } 24 | def pattern = "-(\\d+)-g" 25 | def matcher = version =~ pattern 26 | 27 | if (matcher) { 28 | version = version.substring(0, matcher.start()) + "." + matcher[0][1] 29 | } 30 | 31 | return version 32 | } 33 | 34 | //println gitVersionTag() 35 | 36 | android { 37 | compileSdkVersion 29 38 | buildToolsVersion "29.0.3" 39 | 40 | defaultConfig { 41 | applicationId "com.qc.mycomic" 42 | minSdkVersion 21 43 | targetSdkVersion 29 44 | versionCode gitVersionCode() 45 | versionName gitVersionTag() 46 | 47 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 48 | } 49 | 50 | buildTypes { 51 | release { 52 | minifyEnabled false 53 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 54 | } 55 | } 56 | compileOptions { 57 | sourceCompatibility JavaVersion.VERSION_1_8 58 | targetCompatibility JavaVersion.VERSION_1_8 59 | } 60 | 61 | applicationVariants.all { 62 | variant -> 63 | variant.outputs.all { 64 | outputFileName = "MyComic-${variant.versionName}.apk" 65 | } 66 | } 67 | 68 | } 69 | 70 | dependencies { 71 | implementation fileTree(dir: "libs", include: ["*.jar"]) 72 | implementation project(path: ':common') 73 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/qc/mycomic/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.qc.mycomic; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.qc.mycomic", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/assets/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/assets/1.jpg -------------------------------------------------------------------------------- /app/src/main/assets/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/assets/2.jpg -------------------------------------------------------------------------------- /app/src/main/assets/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/assets/3.jpg -------------------------------------------------------------------------------- /app/src/main/assets/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/assets/4.jpg -------------------------------------------------------------------------------- /app/src/main/assets/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/assets/5.jpg -------------------------------------------------------------------------------- /app/src/main/assets/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/assets/6.jpg -------------------------------------------------------------------------------- /app/src/main/assets/litepal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/constant/AppConstant.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.constant; 2 | 3 | import the.one.base.util.SdCardUtil; 4 | 5 | /** 6 | * @author LuQiChuang 7 | * @desc 8 | * @date 2021/1/27 21:39 9 | * @ver 1.0 10 | */ 11 | public interface AppConstant { 12 | 13 | String NORMAL_PATH = SdCardUtil.getNormalSDCardPath(); 14 | 15 | String APP_PATH = NORMAL_PATH + "/MyComic"; 16 | 17 | String SHELF_IMG_PATH = APP_PATH + "/ShelfImg"; 18 | 19 | String IMG_PATH = APP_PATH + "/Image"; 20 | 21 | String AUTO_SAVE_PATH = APP_PATH + "/AutoBackup"; 22 | 23 | int COMIC_CODE = 1; 24 | 25 | int READER_CODE = 2; 26 | 27 | int VIDEO_CODE = 3; 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/constant/Constant.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.constant; 2 | 3 | /** 4 | * @author LuQiChuang 5 | * @desc 6 | * @date 2020/8/12 15:25 7 | * @ver 1.0 8 | */ 9 | public interface Constant { 10 | 11 | String TAG = "TAG"; 12 | 13 | int STATUS_HIS = 0; 14 | 15 | int STATUS_FAV = 1; 16 | 17 | int STATUS_ALL = 2; 18 | 19 | int NORMAL = 0; 20 | 21 | int READER_TO_CHAPTER = 1; 22 | 23 | int SEARCH_TO_CHAPTER = 2; 24 | 25 | int RANK_TO_CHAPTER = 3; 26 | 27 | int SCREEN_0 = 0; 28 | 29 | int SCREEN_1 = 1; 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/constant/TmpData.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.constant; 2 | 3 | import com.qc.common.en.SettingEnum; 4 | import com.qc.common.util.SettingUtil; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author LuQiChuang 11 | * @desc 12 | * @date 2021/1/27 22:06 13 | * @ver 1.0 14 | */ 15 | public class TmpData { 16 | 17 | public static int toStatus = Constant.NORMAL; 18 | 19 | public static boolean isLight = true; 20 | 21 | public static boolean isFull = (boolean) SettingUtil.getSettingKey(SettingEnum.IS_FULL_SCREEN); 22 | 23 | public static int contentCode = (int) SettingUtil.getSettingKey(SettingEnum.READ_CONTENT); 24 | 25 | public static String content = SettingUtil.getSettingDesc(SettingEnum.READ_CONTENT); 26 | 27 | public static int videoSpeed = 2; 28 | 29 | public static Map map = new HashMap<>(); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/en/SettingEnum.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.en; 2 | 3 | import com.qc.common.constant.AppConstant; 4 | 5 | import java.util.LinkedHashMap; 6 | 7 | import top.luqichuang.common.en.NSourceEnum; 8 | import top.luqichuang.common.en.SourceEnum; 9 | import top.luqichuang.common.en.VSourceEnum; 10 | 11 | /** 12 | * @author LuQiChuang 13 | * @desc 14 | * @date 2021/1/16 21:45 15 | * @ver 1.0 16 | */ 17 | public enum SettingEnum { 18 | 19 | DEFAULT_SOURCE("defaultSource", SourceEnum.MI_TUI.ID), 20 | PRELOAD_NUM("preloadNum", 10000), 21 | READ_CONTENT("readContent", AppConstant.COMIC_CODE), 22 | DEFAULT_NOVEL_SOURCE("defaultNSource", NSourceEnum.AI_YUE.ID), 23 | IS_FULL_SCREEN("isFullScreen", true), 24 | NOVEL_FONT_SIZE("novelFontSize", 20), 25 | NOVEL_AUTO_SPEED("novelAutoSpeed", 4), 26 | VIDEO_PROGRESS("videoProgress", new LinkedHashMap<>()), 27 | DEFAULT_VIDEO_SOURCE("defaultVSource", VSourceEnum.YING_HUA.ID), 28 | COMIC_SOURCE_OPEN("comicSourceOpen", SourceEnum.getMAP().keySet()), 29 | NOVEL_SOURCE_OPEN("novelSourceOpen", NSourceEnum.getMAP().keySet()), 30 | VIDEO_SOURCE_OPEN("videoSourceOpen", VSourceEnum.getMAP().keySet()), 31 | COMIC_SOURCE_TOTAL("comicSourceTotal", SourceEnum.getMAP().keySet()), 32 | NOVEL_SOURCE_TOTAL("novelSourceTotal", SourceEnum.getMAP().keySet()), 33 | VIDEO_SOURCE_TOTAL("videoSourceTotal", SourceEnum.getMAP().keySet()), 34 | ; 35 | 36 | public final String KEY; 37 | public final Object DEFAULT_VALUE; 38 | 39 | SettingEnum(String KEY, Object DEFAULT_VALUE) { 40 | this.KEY = KEY; 41 | this.DEFAULT_VALUE = DEFAULT_VALUE; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/self/CommonData.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.self; 2 | 3 | import com.qc.common.constant.AppConstant; 4 | import com.qc.common.constant.TmpData; 5 | 6 | /** 7 | * @author LuQiChuang 8 | * @desc 9 | * @date 2021/6/9 16:44 10 | * @ver 1.0 11 | */ 12 | public class CommonData { 13 | 14 | private static final String[] COMIC_TAB_BARS = { 15 | "我的画架", 16 | "搜索漫画", 17 | "个人中心", 18 | }; 19 | 20 | private static final String[] NOVEL_TAB_BARS = { 21 | "我的书架", 22 | "搜索小说", 23 | "个人中心", 24 | }; 25 | 26 | private static final String[] VIDEO_TAB_BARS = { 27 | "我的番剧", 28 | "搜索番剧", 29 | "个人中心", 30 | }; 31 | 32 | private static final String[] COMMON_TAB_BARS = { 33 | "主页", 34 | "搜索", 35 | "个人", 36 | }; 37 | 38 | public static String[] getTabBars() { 39 | if (TmpData.contentCode == AppConstant.COMIC_CODE) { 40 | return COMIC_TAB_BARS; 41 | } else if (TmpData.contentCode == AppConstant.READER_CODE) { 42 | return NOVEL_TAB_BARS; 43 | } else if (TmpData.contentCode == AppConstant.VIDEO_CODE) { 44 | return VIDEO_TAB_BARS; 45 | } else { 46 | return COMMON_TAB_BARS; 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/self/ImageConfig.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.self; 2 | 3 | import android.widget.ImageView; 4 | import android.widget.RelativeLayout; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2021/2/24 22:30 12 | * @ver 1.0 13 | */ 14 | public class ImageConfig { 15 | 16 | private String url; 17 | 18 | private Map headers; 19 | 20 | private RelativeLayout layout; 21 | 22 | private Object saveKey; 23 | 24 | private boolean isSave; 25 | 26 | private boolean isForce; 27 | 28 | private int defaultBitmapId; 29 | 30 | private int errorBitmapId; 31 | 32 | private int drawableId; 33 | 34 | private int height; 35 | 36 | private int width; 37 | 38 | private int endHeight; 39 | 40 | private int endWidth; 41 | 42 | private ImageView.ScaleType scaleType; 43 | 44 | public ImageConfig(String url, RelativeLayout layout) { 45 | this.url = url; 46 | this.layout = layout; 47 | } 48 | 49 | public ImageConfig() { 50 | 51 | } 52 | 53 | public String getUrl() { 54 | return url; 55 | } 56 | 57 | public void setUrl(String url) { 58 | this.url = url; 59 | } 60 | 61 | public Map getHeaders() { 62 | return headers; 63 | } 64 | 65 | public void setHeaders(Map headers) { 66 | this.headers = headers; 67 | } 68 | 69 | public RelativeLayout getLayout() { 70 | return layout; 71 | } 72 | 73 | public void setLayout(RelativeLayout layout) { 74 | this.layout = layout; 75 | } 76 | 77 | public Object getSaveKey() { 78 | return saveKey; 79 | } 80 | 81 | public void setSaveKey(Object saveKey) { 82 | this.saveKey = saveKey; 83 | } 84 | 85 | public boolean isSave() { 86 | return isSave; 87 | } 88 | 89 | public void setSave(boolean save) { 90 | isSave = save; 91 | } 92 | 93 | public boolean isForce() { 94 | return isForce; 95 | } 96 | 97 | public void setForce(boolean force) { 98 | isForce = force; 99 | } 100 | 101 | public int getDefaultBitmapId() { 102 | return defaultBitmapId; 103 | } 104 | 105 | public void setDefaultBitmapId(int defaultBitmapId) { 106 | this.defaultBitmapId = defaultBitmapId; 107 | } 108 | 109 | public int getErrorBitmapId() { 110 | return errorBitmapId; 111 | } 112 | 113 | public void setErrorBitmapId(int errorBitmapId) { 114 | this.errorBitmapId = errorBitmapId; 115 | } 116 | 117 | public int getDrawableId() { 118 | return drawableId; 119 | } 120 | 121 | public void setDrawableId(int drawableId) { 122 | this.drawableId = drawableId; 123 | } 124 | 125 | public int getHeight() { 126 | return height; 127 | } 128 | 129 | public void setHeight(int height) { 130 | this.height = height; 131 | } 132 | 133 | public int getWidth() { 134 | return width; 135 | } 136 | 137 | public void setWidth(int width) { 138 | this.width = width; 139 | } 140 | 141 | public int getEndHeight() { 142 | return endHeight; 143 | } 144 | 145 | public void setEndHeight(int endHeight) { 146 | this.endHeight = endHeight; 147 | } 148 | 149 | public int getEndWidth() { 150 | return endWidth; 151 | } 152 | 153 | public void setEndWidth(int endWidth) { 154 | this.endWidth = endWidth; 155 | } 156 | 157 | public ImageView.ScaleType getScaleType() { 158 | return scaleType; 159 | } 160 | 161 | public void setScaleType(ImageView.ScaleType scaleType) { 162 | this.scaleType = scaleType; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/self/ScrollSpeedLinearLayoutManger.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.self; 2 | 3 | import android.content.Context; 4 | import android.graphics.PointF; 5 | import android.util.DisplayMetrics; 6 | 7 | import androidx.recyclerview.widget.LinearLayoutManager; 8 | import androidx.recyclerview.widget.LinearSmoothScroller; 9 | import androidx.recyclerview.widget.RecyclerView; 10 | 11 | import com.qc.common.en.SettingEnum; 12 | import com.qc.common.util.SettingUtil; 13 | 14 | /** 15 | * @author LuQiChuang 16 | * @desc 17 | * @date 2021/4/16 10:21 18 | * @ver 1.0 19 | */ 20 | public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager { 21 | private float MILLISECONDS_PER_INCH = 3f; 22 | 23 | private Context context; 24 | 25 | private int level; 26 | 27 | public ScrollSpeedLinearLayoutManger(Context context) { 28 | super(context); 29 | this.context = context; 30 | } 31 | 32 | @Override 33 | public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { 34 | LinearSmoothScroller linearSmoothScroller = 35 | new LinearSmoothScroller(recyclerView.getContext()) { 36 | @Override 37 | public PointF computeScrollVectorForPosition(int targetPosition) { 38 | return ScrollSpeedLinearLayoutManger.this 39 | .computeScrollVectorForPosition(targetPosition); 40 | } 41 | 42 | //This returns the milliseconds it takes to 43 | //scroll one pixel. 44 | @Override 45 | protected float calculateSpeedPerPixel 46 | (DisplayMetrics displayMetrics) { 47 | return MILLISECONDS_PER_INCH / displayMetrics.density; 48 | //返回滑动一个pixel需要多少毫秒 49 | } 50 | 51 | }; 52 | linearSmoothScroller.setTargetPosition(position); 53 | startSmoothScroll(linearSmoothScroller); 54 | } 55 | 56 | public String addSpeed() { 57 | return changeSpeed(level + 1); 58 | } 59 | 60 | public String subSpeed() { 61 | return changeSpeed(level - 1); 62 | } 63 | 64 | public String changeSpeed(int value) { 65 | if (value >= 1 && value <= 7) { 66 | level = value; 67 | SettingUtil.putSetting(SettingEnum.NOVEL_AUTO_SPEED, level); 68 | MILLISECONDS_PER_INCH = context.getResources().getDisplayMetrics().density * 1.2f * (7 - level + 1); 69 | } 70 | return getSpeedDesc(); 71 | } 72 | 73 | public String getSpeedDesc() { 74 | return String.valueOf(level); 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/self/SnapImageInfo.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.self; 2 | 3 | import the.one.base.Interface.ImageSnap; 4 | import top.luqichuang.common.model.Content; 5 | 6 | /** 7 | * @author LuQiChuang 8 | * @desc 9 | * @date 2021/1/27 22:35 10 | * @ver 1.0 11 | */ 12 | public class SnapImageInfo implements ImageSnap { 13 | 14 | public final Content INFO; 15 | 16 | public SnapImageInfo(Content content) { 17 | this.INFO = content; 18 | } 19 | 20 | @Override 21 | public String getImageUrl() { 22 | return INFO.getUrl(); 23 | } 24 | 25 | @Override 26 | public String getRefer() { 27 | return null; 28 | } 29 | 30 | @Override 31 | public boolean isVideo() { 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/activity/LauncherActivity.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.activity; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.os.Bundle; 7 | import android.widget.Toast; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.appcompat.app.AppCompatActivity; 11 | import androidx.core.app.ActivityCompat; 12 | import androidx.core.content.ContextCompat; 13 | 14 | import com.qc.common.ui.presenter.UpdatePresenter; 15 | import com.qc.common.util.DBUtil; 16 | import com.qc.common.util.EntityUtil; 17 | import com.qc.common.util.VersionUtil; 18 | import com.qmuiteam.qmui.arch.QMUILatestVisit; 19 | 20 | import org.litepal.LitePal; 21 | 22 | /** 23 | * @author LuQiChuang 24 | * @desc 25 | * @date 2020/8/12 15:25 26 | * @ver 1.0 27 | */ 28 | public class LauncherActivity extends AppCompatActivity { 29 | 30 | private static final int PERMISSIONS_REQUEST_CODE = 10; 31 | private static final String[] PERMISSIONS_REQUIRED = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; 32 | private static final String TAG = LauncherActivity.class.getSimpleName(); 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { 38 | finish(); 39 | return; 40 | } 41 | 42 | if (allPermissionsGranted()) { 43 | doAfterPermissionsGranted(); 44 | } else { 45 | ActivityCompat.requestPermissions(this, PERMISSIONS_REQUIRED, PERMISSIONS_REQUEST_CODE); 46 | } 47 | } 48 | 49 | @Override 50 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 51 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 52 | if (requestCode == PERMISSIONS_REQUEST_CODE) { 53 | if (allPermissionsGranted()) { 54 | doAfterPermissionsGranted(); 55 | } else { 56 | Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show(); 57 | finish(); 58 | } 59 | } 60 | } 61 | 62 | private void doAfterPermissionsGranted() { 63 | Intent intent = QMUILatestVisit.intentOfLatestVisit(this); 64 | if (intent == null) { 65 | intent = new Intent(this, MainActivity.class); 66 | } 67 | doSomeThing(); 68 | startActivity(intent); 69 | finish(); 70 | } 71 | 72 | private void doSomeThing() { 73 | VersionUtil.initVersion(this); 74 | new UpdatePresenter().checkApkUpdate(); 75 | LitePal.initialize(this); 76 | EntityUtil.initEntityList(EntityUtil.STATUS_ALL); 77 | new Thread(() -> DBUtil.autoBackup(this)).start(); 78 | } 79 | 80 | private boolean allPermissionsGranted() { 81 | for (String permission : PERMISSIONS_REQUIRED) { 82 | if (ContextCompat.checkSelfPermission(getBaseContext(), permission) != PackageManager.PERMISSION_GRANTED) { 83 | return false; 84 | } 85 | } 86 | return true; 87 | } 88 | 89 | @Override 90 | public void finish() { 91 | super.finish(); 92 | overridePendingTransition(0, 0); 93 | } 94 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.activity; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.qc.common.ui.fragment.MyHomeFragment; 6 | 7 | import the.one.base.ui.activity.BaseFragmentActivity; 8 | import the.one.base.ui.fragment.BaseFragment; 9 | 10 | /** 11 | * @author LuQiChuang 12 | * @desc 13 | * @date 2020/8/12 15:25 14 | * @ver 1.0 15 | */ 16 | public class MainActivity extends BaseFragmentActivity { 17 | 18 | private static MainActivity activity; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | activity = this; 24 | } 25 | 26 | public static MainActivity getInstance() { 27 | return activity; 28 | } 29 | 30 | @Override 31 | protected BaseFragment getFirstFragment() { 32 | return new MyHomeFragment(); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/ChapterAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.view.ViewGroup; 5 | import android.widget.TextView; 6 | 7 | import com.qc.mycomic.R; 8 | import com.qmuiteam.qmui.util.QMUIDisplayHelper; 9 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButtonDrawable; 10 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundLinearLayout; 11 | 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import java.util.Objects; 15 | import java.util.Random; 16 | 17 | import the.one.base.adapter.TheBaseQuickAdapter; 18 | import the.one.base.adapter.TheBaseViewHolder; 19 | import top.luqichuang.common.model.ChapterInfo; 20 | import top.luqichuang.common.model.Entity; 21 | 22 | /** 23 | * @author LuQiChuang 24 | * @desc 25 | * @date 2021/6/10 17:50 26 | * @ver 1.0 27 | */ 28 | public class ChapterAdapter extends TheBaseQuickAdapter { 29 | 30 | private final Entity entity; 31 | 32 | private int chapterId; 33 | 34 | public ChapterAdapter(Entity entity) { 35 | super(R.layout.item_chapter); 36 | this.entity = entity; 37 | this.chapterId = entity.getInfo().getCurChapterId(); 38 | } 39 | 40 | private Random random = new Random(); 41 | 42 | @Override 43 | protected void convert(@NotNull TheBaseViewHolder holder, ChapterInfo chapterInfo) { 44 | holder.setText(R.id.tvTitle, chapterInfo.getTitle()); 45 | TextView tvTitle = holder.findView(R.id.tvTitle); 46 | if (random.nextBoolean()) { 47 | QMUIRoundLinearLayout linearLayout = holder.findView(R.id.linearLayout); 48 | ViewGroup.LayoutParams lp = linearLayout.getLayoutParams(); 49 | lp.width = QMUIDisplayHelper.getScreenWidth(getContext()); 50 | } 51 | if (Objects.equals(chapterInfo.getTitle(), entity.getInfo().getCurChapterTitle())) { 52 | tvTitle.setTextColor(getColor(R.color.white)); 53 | QMUIRoundLinearLayout linearLayout = holder.findView(R.id.linearLayout); 54 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 55 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.colorPrimary)); 56 | drawable.setBgData(colorStateList); 57 | chapterId = chapterInfo.getId(); 58 | } else { 59 | tvTitle.setTextColor(getColor(R.color.black)); 60 | QMUIRoundLinearLayout linearLayout = holder.findView(R.id.linearLayout); 61 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 62 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.white)); 63 | drawable.setBgData(colorStateList); 64 | } 65 | } 66 | 67 | public void setChapterId(int chapterId) { 68 | this.chapterId = chapterId; 69 | } 70 | 71 | public int getChapterId() { 72 | return chapterId; 73 | } 74 | 75 | private static final int NORMAL = 0; 76 | private static final int NEW_LINE = 1; 77 | 78 | @Override 79 | protected int getDefItemViewType(int position) { 80 | return getData().get(position).getStatus(); 81 | } 82 | 83 | // @NotNull 84 | // @Override 85 | // protected TheBaseViewHolder onCreateDefViewHolder(@NotNull ViewGroup parent, int viewType) { 86 | // if (viewType == NEW_LINE) { 87 | // return super.createBaseViewHolder(parent, R.layout.item_rank_right_simple); 88 | // } else { 89 | // return super.onCreateDefViewHolder(parent, viewType); 90 | // } 91 | // } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/ChapterItemAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.widget.TextView; 5 | 6 | import com.qc.mycomic.R; 7 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButtonDrawable; 8 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundLinearLayout; 9 | 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | import java.util.Objects; 13 | 14 | import the.one.base.adapter.TheBaseQuickAdapter; 15 | import the.one.base.adapter.TheBaseViewHolder; 16 | import top.luqichuang.common.model.ChapterInfo; 17 | import top.luqichuang.common.model.Entity; 18 | 19 | /** 20 | * @author LuQiChuang 21 | * @desc 22 | * @date 2021/6/24 16:20 23 | * @ver 1.0 24 | */ 25 | public class ChapterItemAdapter extends TheBaseQuickAdapter { 26 | 27 | private final Entity entity; 28 | 29 | public ChapterItemAdapter(Entity entity) { 30 | super(R.layout.item_chapter); 31 | this.entity = entity; 32 | } 33 | 34 | @Override 35 | protected void convert(@NotNull TheBaseViewHolder holder, ChapterInfo chapterInfo) { 36 | holder.setText(R.id.tvTitle, chapterInfo.getTitle()); 37 | TextView tvTitle = holder.findView(R.id.tvTitle); 38 | if (Objects.equals(chapterInfo.getId(), entity.getInfo().getCurChapterId())) { 39 | tvTitle.setTextColor(getColor(R.color.white)); 40 | QMUIRoundLinearLayout linearLayout = holder.findView(R.id.linearLayout); 41 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 42 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.colorPrimary)); 43 | drawable.setBgData(colorStateList); 44 | } else { 45 | tvTitle.setTextColor(getColor(R.color.black)); 46 | QMUIRoundLinearLayout linearLayout = holder.findView(R.id.linearLayout); 47 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 48 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.white)); 49 | drawable.setBgData(colorStateList); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/ComicReaderAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.widget.RelativeLayout; 4 | 5 | import com.qc.common.self.ImageConfig; 6 | import com.qc.common.util.EntityHelper; 7 | import com.qc.common.util.ImgUtil; 8 | import com.qc.mycomic.R; 9 | 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | import the.one.base.adapter.TheBaseQuickAdapter; 13 | import the.one.base.adapter.TheBaseViewHolder; 14 | import top.luqichuang.common.model.Content; 15 | import top.luqichuang.common.model.Entity; 16 | import top.luqichuang.common.model.Source; 17 | 18 | /** 19 | * @author LuQiChuang 20 | * @desc 21 | * @date 2021/6/11 9:52 22 | * @ver 1.0 23 | */ 24 | public class ComicReaderAdapter extends TheBaseQuickAdapter { 25 | 26 | private Entity entity; 27 | 28 | public ComicReaderAdapter(int layoutResId, Entity entity) { 29 | super(layoutResId); 30 | this.entity = entity; 31 | } 32 | 33 | @Override 34 | protected void convert(@NotNull TheBaseViewHolder holder, Content content) { 35 | RelativeLayout layout = holder.findView(R.id.imageRelativeLayout); 36 | ImageConfig config = ImgUtil.getReaderConfig(getContext(), content.getUrl(), layout); 37 | Source source = EntityHelper.commonSource(entity); 38 | config.setHeaders(source.getImageHeaders()); 39 | ImgUtil.loadImage(getContext(), config); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/NovelReaderAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.widget.TextView; 4 | 5 | import androidx.annotation.Dimension; 6 | 7 | import com.qc.common.en.SettingEnum; 8 | import com.qc.common.util.EntityHelper; 9 | import com.qc.common.util.SettingUtil; 10 | import com.qc.mycomic.R; 11 | 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import java.util.List; 15 | 16 | import the.one.base.adapter.TheBaseQuickAdapter; 17 | import the.one.base.adapter.TheBaseViewHolder; 18 | import top.luqichuang.common.model.ChapterInfo; 19 | import top.luqichuang.common.model.Content; 20 | import top.luqichuang.mynovel.model.NovelInfo; 21 | 22 | /** 23 | * @author LuQiChuang 24 | * @desc 25 | * @date 2021/6/11 9:52 26 | * @ver 1.0 27 | */ 28 | public class NovelReaderAdapter extends TheBaseQuickAdapter { 29 | 30 | private List chapterInfoList; 31 | private NovelInfo novelInfo; 32 | private int fontSize = (int) SettingUtil.getSettingKey(SettingEnum.NOVEL_FONT_SIZE); 33 | 34 | public NovelReaderAdapter(int layoutResId, NovelInfo novelInfo) { 35 | super(layoutResId); 36 | this.novelInfo = novelInfo; 37 | this.chapterInfoList = novelInfo.getChapterInfoList(); 38 | } 39 | 40 | @Override 41 | protected void convert(@NotNull TheBaseViewHolder holder, Content content) { 42 | int position = EntityHelper.getPosition(novelInfo, content.getChapterId()); 43 | holder.setText(R.id.tvTitle, chapterInfoList.get(position).getTitle()); 44 | TextView tvContent = holder.getView(R.id.tvContent); 45 | tvContent.setText(content.getContent()); 46 | tvContent.setTextSize(Dimension.SP, fontSize); 47 | } 48 | 49 | public String addFont() { 50 | return changeFontSize(fontSize + 1); 51 | } 52 | 53 | public String subFont() { 54 | return changeFontSize(fontSize - 1); 55 | } 56 | 57 | private String changeFontSize(int value) { 58 | if (value >= 16 && value <= 30) { 59 | fontSize = value; 60 | SettingUtil.putSetting(SettingEnum.NOVEL_FONT_SIZE, fontSize); 61 | notifyDataSetChanged(); 62 | } 63 | return getFontSizeDesc(); 64 | } 65 | 66 | public String getFontSizeDesc() { 67 | return fontSize + "sp"; 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/RankAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.view.View; 4 | import android.view.ViewGroup; 5 | import android.widget.RelativeLayout; 6 | import android.widget.TextView; 7 | 8 | import com.qc.common.self.ImageConfig; 9 | import com.qc.common.util.EntityHelper; 10 | import com.qc.common.util.ImgUtil; 11 | import com.qc.mycomic.R; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | import the.one.base.adapter.TheBaseQuickAdapter; 16 | import the.one.base.adapter.TheBaseViewHolder; 17 | import top.luqichuang.common.model.Entity; 18 | import top.luqichuang.common.model.Source; 19 | 20 | /** 21 | * @author LuQiChuang 22 | * @desc 23 | * @date 2021/6/11 11:45 24 | * @ver 1.0 25 | */ 26 | public class RankAdapter extends TheBaseQuickAdapter { 27 | 28 | public static final int NO_IMG = -1; 29 | 30 | public RankAdapter(int layoutResId) { 31 | super(layoutResId); 32 | } 33 | 34 | @Override 35 | protected void convert(@NotNull TheBaseViewHolder holder, Entity entity) { 36 | holder.setText(R.id.tvTitle, entity.getInfo().getTitle()); 37 | holder.setText(R.id.tvAuthor, entity.getInfo().getAuthor()); 38 | TextView tvUpdateTime = holder.findView(R.id.tvUpdateTime); 39 | String updateTime = entity.getInfo().getUpdateTime(); 40 | if (tvUpdateTime != null && updateTime != null) { 41 | tvUpdateTime.setVisibility(View.VISIBLE); 42 | tvUpdateTime.setText(updateTime); 43 | } else if (tvUpdateTime != null) { 44 | goneView(tvUpdateTime); 45 | } 46 | holder.setText(R.id.tvIndex, String.valueOf(holder.getAdapterPosition() + 1)); 47 | RelativeLayout relativeLayout = holder.findView(R.id.imageRelativeLayout); 48 | ImageConfig config = ImgUtil.getDefaultConfig(getContext(), entity.getInfo().getImgUrl(), relativeLayout); 49 | Source source = EntityHelper.commonSource(entity); 50 | config.setHeaders(source.getImageHeaders()); 51 | ImgUtil.loadImage(getContext(), config); 52 | } 53 | 54 | @Override 55 | protected int getDefItemViewType(int position) { 56 | if (getData().get(position).getInfo().getImgUrl() == null) { 57 | return NO_IMG; 58 | } 59 | return super.getDefItemViewType(position); 60 | } 61 | 62 | @NotNull 63 | @Override 64 | protected TheBaseViewHolder onCreateDefViewHolder(@NotNull ViewGroup parent, int viewType) { 65 | if (viewType == NO_IMG) { 66 | return super.createBaseViewHolder(parent, R.layout.item_rank_right_simple); 67 | } else { 68 | return super.onCreateDefViewHolder(parent, viewType); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/RankLeftAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.widget.TextView; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | import com.qc.mycomic.R; 9 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButtonDrawable; 10 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundLinearLayout; 11 | 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import java.util.List; 15 | 16 | import the.one.base.adapter.TheBaseQuickAdapter; 17 | import the.one.base.adapter.TheBaseViewHolder; 18 | 19 | /** 20 | * @author LuQiChuang 21 | * @desc 22 | * @date 2020/8/12 15:25 23 | * @ver 1.0 24 | */ 25 | public class RankLeftAdapter extends TheBaseQuickAdapter { 26 | 27 | private int position = 0; 28 | 29 | public RankLeftAdapter(int layoutResId, @Nullable List data) { 30 | super(layoutResId, data); 31 | } 32 | 33 | @Override 34 | protected void convert(@NotNull TheBaseViewHolder holder, String s) { 35 | TextView textView = holder.getView(R.id.textView); 36 | QMUIRoundLinearLayout linearLayout = holder.findView(R.id.linearLayout); 37 | if (linearLayout != null) { 38 | if (position == holder.getAdapterPosition()) { 39 | textView.setText(s); 40 | textView.setTextColor(getColor(R.color.white)); 41 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 42 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.qmui_config_color_blue)); 43 | drawable.setBgData(colorStateList); 44 | } else { 45 | textView.setText(s); 46 | textView.setTextColor(getColor(R.color.black)); 47 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 48 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.white)); 49 | drawable.setBgData(colorStateList); 50 | } 51 | } 52 | } 53 | 54 | public void setPosition(int position) { 55 | this.position = position; 56 | notifyDataSetChanged(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/ReaderListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.widget.TextView; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | import com.qc.mycomic.R; 9 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButtonDrawable; 10 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundLinearLayout; 11 | 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import java.util.List; 15 | 16 | import the.one.base.adapter.TheBaseQuickAdapter; 17 | import the.one.base.adapter.TheBaseViewHolder; 18 | import top.luqichuang.common.model.ChapterInfo; 19 | 20 | /** 21 | * @author LuQiChuang 22 | * @desc 23 | * @date 2021/2/28 12:48 24 | * @ver 1.0 25 | */ 26 | public class ReaderListAdapter extends TheBaseQuickAdapter { 27 | 28 | private int position = 0; 29 | 30 | public ReaderListAdapter(int layoutResId, @Nullable List data) { 31 | super(layoutResId, data); 32 | } 33 | 34 | @Override 35 | protected void convert(@NotNull TheBaseViewHolder holder, ChapterInfo chapterInfo) { 36 | TextView textView = holder.getView(R.id.textView); 37 | QMUIRoundLinearLayout linearLayout = holder.findView(R.id.linearLayout); 38 | if (linearLayout != null) { 39 | if (position == holder.getAdapterPosition()) { 40 | textView.setText(chapterInfo.getTitle()); 41 | textView.setTextColor(getColor(R.color.white)); 42 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 43 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.qmui_config_color_blue)); 44 | drawable.setBgData(colorStateList); 45 | } else { 46 | textView.setText(chapterInfo.getTitle()); 47 | textView.setTextColor(getColor(R.color.black)); 48 | QMUIRoundButtonDrawable drawable = (QMUIRoundButtonDrawable) linearLayout.getBackground(); 49 | ColorStateList colorStateList = ColorStateList.valueOf(getColor(R.color.white)); 50 | drawable.setBgData(colorStateList); 51 | } 52 | } 53 | } 54 | 55 | public int getPosition() { 56 | return position; 57 | } 58 | 59 | public void setPosition(int position) { 60 | this.position = position; 61 | notifyDataSetChanged(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/SearchAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.widget.RelativeLayout; 4 | 5 | import com.qc.common.constant.TmpData; 6 | import com.qc.common.self.ImageConfig; 7 | import com.qc.common.util.EntityHelper; 8 | import com.qc.common.util.ImgUtil; 9 | import com.qc.mycomic.R; 10 | 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | import the.one.base.adapter.TheBaseQuickAdapter; 14 | import the.one.base.adapter.TheBaseViewHolder; 15 | import top.luqichuang.common.model.Entity; 16 | import top.luqichuang.common.model.Source; 17 | 18 | /** 19 | * @author LuQiChuang 20 | * @desc 21 | * @date 2021/6/11 15:33 22 | * @ver 1.0 23 | */ 24 | public class SearchAdapter extends TheBaseQuickAdapter { 25 | 26 | public SearchAdapter(int layoutResId) { 27 | super(layoutResId); 28 | } 29 | 30 | @Override 31 | protected void convert(@NotNull TheBaseViewHolder holder, Entity entity) { 32 | holder.setText(R.id.tvTitle, entity.getInfo().getTitle()); 33 | holder.setText(R.id.tvSource, TmpData.content + "源数量:" + EntityHelper.sourceSize(entity)); 34 | holder.setText(R.id.tvAuthor, entity.getInfo().getAuthor()); 35 | holder.setText(R.id.tvUpdateTime, entity.getInfo().getUpdateTime()); 36 | RelativeLayout layout = holder.findView(R.id.imageRelativeLayout); 37 | ImageConfig config = ImgUtil.getDefaultConfig(getContext(), entity.getInfo().getImgUrl(), layout); 38 | Source source = EntityHelper.commonSource(entity); 39 | config.setHeaders(source.getImageHeaders()); 40 | ImgUtil.loadImage(getContext(), config); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/adapter/ShelfAdapter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.adapter; 2 | 3 | import android.view.View; 4 | import android.widget.LinearLayout; 5 | import android.widget.RelativeLayout; 6 | 7 | import com.qc.common.constant.AppConstant; 8 | import com.qc.common.constant.TmpData; 9 | import com.qc.common.self.ImageConfig; 10 | import com.qc.common.util.EntityHelper; 11 | import com.qc.common.util.ImgUtil; 12 | import com.qc.mycomic.R; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | import the.one.base.adapter.TheBaseQuickAdapter; 17 | import the.one.base.adapter.TheBaseViewHolder; 18 | import top.luqichuang.common.model.Entity; 19 | import top.luqichuang.common.model.Source; 20 | 21 | /** 22 | * @author LuQiChuang 23 | * @desc 24 | * @date 2021/6/9 18:43 25 | * @ver 1.0 26 | */ 27 | public class ShelfAdapter extends TheBaseQuickAdapter { 28 | 29 | public ShelfAdapter() { 30 | super(R.layout.item_shelf); 31 | } 32 | 33 | @Override 34 | protected void convert(@NotNull TheBaseViewHolder holder, Entity entity) { 35 | holder.setText(R.id.tvTitle, entity.getTitle()); 36 | String readText = entity.getCurChapterTitle(); 37 | if (readText == null) { 38 | readText = "未阅读"; 39 | } 40 | holder.setText(R.id.tvCurChapter, "阅读至:" + readText); 41 | String updateChapter = entity.getUpdateChapter(); 42 | if (updateChapter == null) { 43 | updateChapter = "未知"; 44 | } 45 | holder.setText(R.id.tvChapter, "更新至:" + updateChapter); 46 | 47 | LinearLayout updateLayout = holder.findView(R.id.llTextUpdate); 48 | if (updateLayout != null) { 49 | if (entity.isUpdate()) { 50 | updateLayout.setVisibility(View.VISIBLE); 51 | } else { 52 | updateLayout.setVisibility(View.GONE); 53 | } 54 | } 55 | RelativeLayout layout = holder.findView(R.id.imageRelativeLayout); 56 | ImageConfig config = ImgUtil.getDefaultConfig(getContext(), entity.getImgUrl(), layout); 57 | config.setSave(true); 58 | if (entity.getInfoId() == 0) { 59 | config.setSaveKey(null); 60 | } else { 61 | if (TmpData.contentCode == AppConstant.COMIC_CODE) { 62 | config.setSaveKey(entity.getInfoId()); 63 | } else if (TmpData.contentCode == AppConstant.READER_CODE) { 64 | config.setSaveKey("N" + entity.getInfoId()); 65 | } else { 66 | config.setSaveKey("V" + entity.getInfoId()); 67 | } 68 | } 69 | Source source = EntityHelper.commonSource(entity); 70 | config.setHeaders(source.getImageHeaders()); 71 | ImgUtil.loadImage(getContext(), config); 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/fragment/MyHomeFragment.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.fragment; 2 | 3 | import com.qc.common.self.CommonData; 4 | import com.qc.mycomic.R; 5 | 6 | import java.util.ArrayList; 7 | 8 | import the.one.base.ui.fragment.BaseFragment; 9 | import the.one.base.ui.fragment.BaseHomeFragment; 10 | 11 | /** 12 | * @author LuQiChuang 13 | * @desc HOME界面 14 | * @date 2020/8/12 15:26 15 | * @ver 1.0 16 | */ 17 | public class MyHomeFragment extends BaseHomeFragment { 18 | 19 | @Override 20 | protected boolean isExitFragment() { 21 | return true; 22 | } 23 | 24 | @Override 25 | protected boolean isNeedChangeStatusBarMode() { 26 | return true; 27 | } 28 | 29 | @Override 30 | protected boolean isViewPagerSwipe() { 31 | return false; 32 | } 33 | 34 | @Override 35 | protected boolean isDestroyItem() { 36 | return false; 37 | } 38 | 39 | @Override 40 | protected void addTabs() { 41 | addTab(R.drawable.ic_baseline_home_24, R.drawable.ic_baseline_home_select_24, CommonData.getTabBars()[0]); 42 | addTab(R.drawable.ic_baseline_search_24, R.drawable.ic_baseline_search_select_24, CommonData.getTabBars()[1]); 43 | addTab(R.drawable.ic_baseline_person_24, R.drawable.ic_baseline_person_select_24, CommonData.getTabBars()[2]); 44 | } 45 | 46 | @Override 47 | protected void addFragment(ArrayList fragments) { 48 | fragments.add(new ShelfFragment()); 49 | fragments.add(new SearchBaseFragment()); 50 | fragments.add(new PersonFragment()); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/fragment/PersonReaderFragment.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.fragment; 2 | 3 | import android.view.Gravity; 4 | import android.view.View; 5 | 6 | import com.qc.mycomic.R; 7 | import com.qc.common.en.SettingEnum; 8 | 9 | import top.luqichuang.common.util.MapUtil; 10 | 11 | import com.qc.common.util.PopupUtil; 12 | import com.qc.common.util.SettingItemUtil; 13 | import com.qc.common.util.SettingUtil; 14 | import com.qmuiteam.qmui.qqface.QMUIQQFaceView; 15 | import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet; 16 | import com.qmuiteam.qmui.widget.grouplist.QMUICommonListItemView; 17 | 18 | import java.util.Map; 19 | 20 | import the.one.base.ui.fragment.BaseGroupListFragment; 21 | 22 | /** 23 | * @author LuQiChuang 24 | * @desc 25 | * @date 2021/1/1 14:50 26 | * @ver 1.0 27 | */ 28 | public class PersonReaderFragment extends BaseGroupListFragment implements View.OnClickListener { 29 | 30 | private QMUICommonListItemView v1, v2, v3, v4, v5, v6; 31 | 32 | @Override 33 | protected void initView(View view) { 34 | super.initView(view); 35 | QMUIQQFaceView mTitle = mTopLayout.setTitle("阅读配置"); 36 | mTopLayout.setTitleGravity(Gravity.CENTER); 37 | mTitle.setTextColor(getColorr(R.color.qmui_config_color_gray_1)); 38 | mTitle.getPaint().setFakeBoldText(true); 39 | addTopBarBackBtn(); 40 | } 41 | 42 | @Override 43 | protected void addGroupListView() { 44 | v1 = CreateDetailItemView("阅读预加载图片数量", SettingUtil.getSettingDesc(SettingEnum.PRELOAD_NUM)); 45 | // v2 = CreateDetailItemView("选择画质", SettingFactory.getInstance().getSetting(SettingFactory.SETTING_COMPRESS_IMAGE).getDetailDesc()); 46 | // addToGroup("阅读配置", v1, v2); 47 | addToGroup("漫画", v1); 48 | } 49 | 50 | @Override 51 | public void onClick(View view) { 52 | if (view == v1) { 53 | Object key = SettingUtil.getSettingKey(SettingEnum.PRELOAD_NUM); 54 | Map map = SettingItemUtil.getMap(SettingEnum.PRELOAD_NUM); 55 | PopupUtil.showSimpleBottomSheetList(getContext(), map, key, "选择预加载图片数量", new QMUIBottomSheet.BottomListSheetBuilder.OnSheetItemClickListener() { 56 | @Override 57 | public void onClick(QMUIBottomSheet dialog, View itemView, int position, String tag) { 58 | Object key = MapUtil.getKeyByValue(map, tag); 59 | SettingUtil.putSetting(SettingEnum.PRELOAD_NUM, key, tag); 60 | v1.setDetailText(tag); 61 | dialog.dismiss(); 62 | } 63 | }); 64 | // } else if (view == v2) { 65 | // Setting setting = SettingFactory.getInstance().getSetting(SettingFactory.SETTING_COMPRESS_IMAGE); 66 | // PopupUtil.showSimpleBottomSheetList(getContext(), setting.getMap(), setting.getData(), "选择画质(如发生卡顿、闪退请选择低画质)", new QMUIBottomSheet.BottomListSheetBuilder.OnSheetItemClickListener() { 67 | // @Override 68 | // public void onClick(QMUIBottomSheet dialog, View itemView, int position, String tag) { 69 | // setting.setData(MapUtil.getKeyByValue(setting.getMap(), tag)); 70 | // v5.setDetailText(tag); 71 | // dialog.dismiss(); 72 | // } 73 | // }); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/fragment/ReaderDetailFragment.java: -------------------------------------------------------------------------------- 1 | package com.qc.mycomic.ui.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.view.Gravity; 5 | import android.view.View; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | import com.qc.common.self.SnapImageInfo; 10 | import com.qc.common.util.EntityHelper; 11 | import com.qc.mycomic.R; 12 | import com.qmuiteam.qmui.qqface.QMUIQQFaceView; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import the.one.base.ui.fragment.BaseImageSnapFragment; 18 | import the.one.base.ui.presenter.BasePresenter; 19 | import top.luqichuang.common.model.Content; 20 | 21 | /** 22 | * @author LuQiChuang 23 | * @desc 图片放大界面 24 | * @date 2021/6/11 17:48 25 | * @ver 1.0 26 | */ 27 | public class ReaderDetailFragment extends BaseImageSnapFragment { 28 | 29 | private SnapImageInfo snapImageInfo; 30 | 31 | private final List LIST = new ArrayList<>(); 32 | 33 | public static ReaderDetailFragment getInstance(Content content) { 34 | ReaderDetailFragment fragment = new ReaderDetailFragment(); 35 | Bundle bundle = new Bundle(); 36 | bundle.putSerializable("content", content); 37 | fragment.setArguments(bundle); 38 | return fragment; 39 | } 40 | 41 | @Override 42 | public void onCreate(@Nullable Bundle savedInstanceState) { 43 | Content content = (Content) getArguments().get("content"); 44 | this.snapImageInfo = new SnapImageInfo(content); 45 | this.LIST.add(snapImageInfo); 46 | super.onCreate(savedInstanceState); 47 | } 48 | 49 | @Override 50 | protected void initAdapter() { 51 | super.initAdapter(); 52 | adapter.getLoadMoreModule().setOnLoadMoreListener(null); 53 | } 54 | 55 | @Override 56 | protected void initView(View rootView) { 57 | super.initView(rootView); 58 | String title = EntityHelper.toStringProgress(snapImageInfo.INFO); 59 | QMUIQQFaceView mTitle = mTopLayout.setTitle(title); 60 | mTopLayout.setTitleGravity(Gravity.CENTER); 61 | mTitle.setTextColor(getColorr(R.color.qmui_config_color_gray_1)); 62 | mTitle.getPaint().setFakeBoldText(true); 63 | } 64 | 65 | 66 | @Override 67 | protected void onScrollChanged(SnapImageInfo item, int position) { 68 | 69 | } 70 | 71 | @Override 72 | public void onVideoClick(SnapImageInfo data) { 73 | 74 | } 75 | 76 | @Override 77 | public boolean onImageLongClick(SnapImageInfo data) { 78 | return false; 79 | } 80 | 81 | @Override 82 | protected void requestServer() { 83 | onComplete(LIST); 84 | } 85 | 86 | @Override 87 | public BasePresenter getPresenter() { 88 | return null; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/fragment/SearchBaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.fragment; 2 | 3 | import android.view.Gravity; 4 | import android.view.View; 5 | 6 | import com.qc.common.constant.AppConstant; 7 | import com.qc.common.constant.TmpData; 8 | import com.qc.mycomic.R; 9 | import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton; 10 | import com.qmuiteam.qmui.qqface.QMUIQQFaceView; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import the.one.base.ui.fragment.BaseFragment; 16 | import the.one.base.ui.fragment.BaseTitleTabFragment; 17 | import top.luqichuang.common.model.Source; 18 | import top.luqichuang.common.util.SourceUtil; 19 | 20 | /** 21 | * @author LuQiChuang 22 | * @desc 23 | * @date 2021/6/11 11:23 24 | * @ver 1.0 25 | */ 26 | public class SearchBaseFragment extends BaseTitleTabFragment { 27 | 28 | private List sourceList; 29 | 30 | @Override 31 | protected void initView(View rootView) { 32 | super.initView(rootView); 33 | QMUIQQFaceView mTitle = mTopLayout.setTitle("排行榜"); 34 | mTopLayout.setNeedChangedWithTheme(false); 35 | mTopLayout.setTitleGravity(Gravity.CENTER); 36 | mTitle.setTextColor(getColorr(R.color.qmui_config_color_gray_1)); 37 | mTitle.getPaint().setFakeBoldText(true); 38 | 39 | QMUIAlphaImageButton ibSearch = mTopLayout.addRightImageButton(R.drawable.ic_baseline_search_24, R.id.topbar_right_button1); 40 | ibSearch.setOnClickListener(v -> { 41 | startFragment(new SearchFragment()); 42 | }); 43 | initList(); 44 | } 45 | 46 | private void initList() { 47 | if (TmpData.contentCode == AppConstant.COMIC_CODE) { 48 | sourceList = (List) SourceUtil.getSourceList(); 49 | } else if (TmpData.contentCode == AppConstant.READER_CODE) { 50 | sourceList = (List) SourceUtil.getNSourceList(); 51 | } else { 52 | sourceList = (List) SourceUtil.getVSourceList(); 53 | } 54 | } 55 | 56 | @Override 57 | protected void addTabs() { 58 | for (Source source : sourceList) { 59 | if (source.isValid() && source.getRankMap() != null) { 60 | addTab(source.getSourceName()); 61 | } 62 | } 63 | } 64 | 65 | @Override 66 | protected void addFragment(ArrayList fragments) { 67 | for (Source source : sourceList) { 68 | if (source.isValid() && source.getRankMap() != null) { 69 | fragments.add(RankFragment.getInstance(source.getSourceId())); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/fragment/SearchFragment.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.fragment; 2 | 3 | import android.view.View; 4 | import android.widget.EditText; 5 | 6 | import com.qc.mycomic.R; 7 | import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; 8 | 9 | import the.one.base.ui.fragment.BaseFragment; 10 | import the.one.base.ui.presenter.BasePresenter; 11 | import the.one.base.widge.TheSearchView; 12 | 13 | /** 14 | * @author LuQiChuang 15 | * @desc 16 | * @date 2021/6/11 15:30 17 | * @ver 1.0 18 | */ 19 | public class SearchFragment extends BaseFragment { 20 | 21 | @Override 22 | protected int getContentViewId() { 23 | return R.layout.fragment_search_result; 24 | } 25 | 26 | @Override 27 | protected void initView(View rootView) { 28 | addTopBarBackBtn(); 29 | QMUIRoundButton btSearch = new QMUIRoundButton(_mActivity); 30 | btSearch.setText("搜索"); 31 | btSearch.setLetterSpacing(0.2f); 32 | mTopLayout.addRightView(btSearch, R.id.topbar_right_view); 33 | 34 | TheSearchView searchView = new TheSearchView(_mActivity); 35 | searchView.setOnTextChangedListener(new TheSearchView.OnTextChangedListener() { 36 | String content = ""; 37 | boolean isEmpty = true; 38 | 39 | @Override 40 | public void onChanged(String content, boolean isEmpty) { 41 | this.content = content; 42 | this.isEmpty = isEmpty; 43 | } 44 | 45 | @Override 46 | public void onSearch() { 47 | if (isEmpty) { 48 | showFailTips("请输入搜索内容"); 49 | } else { 50 | startFragment(SearchResultFragment.getInstance(content)); 51 | } 52 | } 53 | }); 54 | mTopLayout.setCenterView(searchView); 55 | 56 | btSearch.setOnClickListener(v -> { 57 | EditText etSearch = searchView.getSearchEditText(); 58 | String searchString = etSearch.getText().toString(); 59 | if (searchString.trim().equals("")) { 60 | showFailTips("请输入搜索内容"); 61 | } else { 62 | startFragment(SearchResultFragment.getInstance(searchString)); 63 | } 64 | }); 65 | } 66 | 67 | @Override 68 | public BasePresenter getPresenter() { 69 | return null; 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/fragment/ShelfFragment.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.fragment; 2 | 3 | import android.view.Gravity; 4 | import android.view.View; 5 | 6 | import com.qc.common.constant.Constant; 7 | import com.qc.common.constant.TmpData; 8 | import com.qc.common.self.CommonData; 9 | import com.qc.mycomic.R; 10 | import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton; 11 | import com.qmuiteam.qmui.qqface.QMUIQQFaceView; 12 | import com.qmuiteam.qmui.util.QMUIColorHelper; 13 | import com.qmuiteam.qmui.widget.popup.QMUIPopup; 14 | 15 | import java.util.ArrayList; 16 | 17 | import the.one.base.ui.fragment.BaseFragment; 18 | import the.one.base.ui.fragment.BaseTitleTabFragment; 19 | import the.one.base.util.QMUIPopupUtil; 20 | 21 | /** 22 | * @author LuQiChuang 23 | * @desc 24 | * @date 2021/6/9 16:26 25 | * @ver 1.0 26 | */ 27 | public class ShelfFragment extends BaseTitleTabFragment { 28 | 29 | private QMUIQQFaceView mTitle; 30 | private QMUIAlphaImageButton mSettingIcon; 31 | private QMUIPopup mSettingPopup; 32 | 33 | @Override 34 | protected boolean isAdjustMode() { 35 | return true; 36 | } 37 | 38 | @Override 39 | protected boolean showElevation() { 40 | return true; 41 | } 42 | 43 | @Override 44 | protected boolean isFoldTitleBar() { 45 | return true; 46 | } 47 | 48 | @Override 49 | protected void onScrollChanged(float percent) { 50 | mTitle.setTextColor(QMUIColorHelper.setColorAlpha(getColorr(R.color.qmui_config_color_gray_1), percent)); 51 | mSettingIcon.setAlpha(percent); 52 | } 53 | 54 | @Override 55 | protected void initView(View rootView) { 56 | super.initView(rootView); 57 | mTitle = mTopLayout.setTitle(CommonData.getTabBars()[0]); 58 | mTopLayout.setNeedChangedWithTheme(false); 59 | mTopLayout.setTitleGravity(Gravity.CENTER); 60 | mTitle.setTextColor(getColorr(R.color.qmui_config_color_gray_1)); 61 | mTitle.getPaint().setFakeBoldText(true); 62 | 63 | mSettingIcon = mTopLayout.addRightImageButton(R.drawable.ic_baseline_menu_24, R.id.topbar_right_button1); 64 | mSettingIcon.setOnClickListener(v -> { 65 | showSettingPopup(); 66 | }); 67 | } 68 | 69 | private final String[] menus = { 70 | "检查更新", 71 | "筛选" + TmpData.content, 72 | "取消筛选", 73 | "导入" + TmpData.content, 74 | }; 75 | 76 | private void showSettingPopup() { 77 | if (null == mSettingPopup) { 78 | mSettingPopup = QMUIPopupUtil.createListPop(_mActivity, menus, (adapter, view, position) -> { 79 | ShelfItemFragment fragment = (ShelfItemFragment) fragments.get(INDEX); 80 | if (position == 0) { 81 | fragment.startCheckUpdate(); 82 | } else if (position == 1) { 83 | fragment.screen(true); 84 | } else if (position == 2) { 85 | fragment.screen(false); 86 | } else if (position == 3) { 87 | fragment.importMH(); 88 | } else if (position == 4) { 89 | } 90 | mSettingPopup.dismiss(); 91 | }); 92 | } 93 | mSettingPopup.show(mSettingIcon); 94 | } 95 | 96 | @Override 97 | protected void addTabs() { 98 | addTab("收藏" + TmpData.content); 99 | addTab("历史" + TmpData.content); 100 | } 101 | 102 | @Override 103 | protected void addFragment(ArrayList fragments) { 104 | fragments.add(ShelfItemFragment.getInstance(Constant.STATUS_FAV)); 105 | fragments.add(ShelfItemFragment.getInstance(Constant.STATUS_HIS)); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/presenter/ChapterPresenter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.presenter; 2 | 3 | import com.qc.common.constant.AppConstant; 4 | import com.qc.common.constant.TmpData; 5 | import com.qc.common.ui.view.ChapterView; 6 | import com.qc.common.util.EntityHelper; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import io.reactivex.android.schedulers.AndroidSchedulers; 12 | import okhttp3.Request; 13 | import the.one.base.ui.presenter.BasePresenter; 14 | import top.luqichuang.common.model.Entity; 15 | import top.luqichuang.common.model.EntityInfo; 16 | import top.luqichuang.common.model.Source; 17 | import top.luqichuang.common.self.CommonCallback; 18 | import top.luqichuang.common.util.NetUtil; 19 | import top.luqichuang.common.util.SourceUtil; 20 | 21 | /** 22 | * @author LuQiChuang 23 | * @desc 24 | * @date 2021/6/10 17:52 25 | * @ver 1.0 26 | */ 27 | public class ChapterPresenter extends BasePresenter { 28 | 29 | public void load(Entity entity) { 30 | Source source = EntityHelper.commonSource(entity); 31 | EntityInfo info = entity.getInfo(); 32 | Request request = source.getDetailRequest(info.getDetailUrl()); 33 | NetUtil.startLoad(new CommonCallback(request, source, Source.DETAIL) { 34 | @Override 35 | public void onFailure(String errorMsg) { 36 | ChapterView view = getView(); 37 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 38 | if (view != null) { 39 | showErrorPage(errorMsg, v -> { 40 | view.showLoadingPage(); 41 | load(entity); 42 | }); 43 | } 44 | }); 45 | } 46 | 47 | @Override 48 | public void onResponse(String html, Map map) { 49 | ChapterView view = getView(); 50 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 51 | if (view != null) { 52 | EntityHelper.setInfoDetail(entity, html, map); 53 | view.loadComplete(); 54 | } 55 | }); 56 | } 57 | }); 58 | } 59 | 60 | public void updateSource(Entity entity) { 61 | List sourceList; 62 | if (TmpData.contentCode == AppConstant.COMIC_CODE) { 63 | sourceList = SourceUtil.getSourceList(); 64 | } else if (TmpData.contentCode == AppConstant.READER_CODE) { 65 | sourceList = SourceUtil.getNSourceList(); 66 | } else { 67 | sourceList = SourceUtil.getVSourceList(); 68 | } 69 | for (Object o : sourceList) { 70 | Source source = (Source) o; 71 | Request request = source.getSearchRequest(entity.getTitle()); 72 | NetUtil.startLoad(new CommonCallback(request, source, Source.SEARCH) { 73 | @Override 74 | public void onFailure(String errorMsg) { 75 | ChapterView view = getView(); 76 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 77 | if (view != null) { 78 | view.updateSourceComplete(null); 79 | } 80 | }); 81 | } 82 | 83 | @Override 84 | public void onResponse(String html, Map map) { 85 | ChapterView view = getView(); 86 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 87 | if (view != null) { 88 | List infoList = source.getInfoList(html); 89 | view.updateSourceComplete(infoList); 90 | } 91 | }); 92 | } 93 | }); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/presenter/RankPresenter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.presenter; 2 | 3 | import com.qc.common.constant.AppConstant; 4 | import com.qc.common.constant.TmpData; 5 | import com.qc.common.ui.view.RankView; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import io.reactivex.android.schedulers.AndroidSchedulers; 13 | import okhttp3.Request; 14 | import the.one.base.ui.presenter.BasePresenter; 15 | import top.luqichuang.common.model.Entity; 16 | import top.luqichuang.common.model.EntityInfo; 17 | import top.luqichuang.common.model.Source; 18 | import top.luqichuang.common.self.CommonCallback; 19 | import top.luqichuang.common.util.NetUtil; 20 | import top.luqichuang.mycomic.model.Comic; 21 | import top.luqichuang.mycomic.model.ComicInfo; 22 | import top.luqichuang.mynovel.model.Novel; 23 | import top.luqichuang.mynovel.model.NovelInfo; 24 | import top.luqichuang.myvideo.model.Video; 25 | import top.luqichuang.myvideo.model.VideoInfo; 26 | 27 | /** 28 | * @author LuQiChuang 29 | * @desc 30 | * @date 2021/6/11 11:46 31 | * @ver 1.0 32 | */ 33 | public class RankPresenter extends BasePresenter { 34 | 35 | private Source source; 36 | private List entityList; 37 | private Map map = new HashMap<>(); 38 | 39 | public RankPresenter(Source source) { 40 | this.source = source; 41 | } 42 | 43 | public void load(String url) { 44 | if (url == null) { 45 | getView().loadComplete(null); 46 | } else { 47 | if (map.containsKey(url)) { 48 | dealHtml(getView(), map.get(url)); 49 | } else { 50 | loadWithNet(source.getRankRequest(url)); 51 | } 52 | } 53 | } 54 | 55 | private void loadWithNet(Request request) { 56 | NetUtil.startLoad(new CommonCallback(request, source, Source.RANK) { 57 | @Override 58 | public void onFailure(String errorMsg) { 59 | RankView view = getView(); 60 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 61 | if (view != null) { 62 | showErrorPage(errorMsg, v -> { 63 | view.showLoadingPage(); 64 | load(request.url().toString()); 65 | }); 66 | } 67 | }); 68 | } 69 | 70 | @Override 71 | public void onResponse(String html, Map map) { 72 | RankView view = getView(); 73 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 74 | if (view != null) { 75 | RankPresenter.this.map.put(request.url().toString(), html); 76 | dealHtml(view, html); 77 | } 78 | }); 79 | } 80 | }); 81 | } 82 | 83 | private void dealHtml(RankView view, String html) { 84 | if (view != null) { 85 | List infoList = source.getRankInfoList(html); 86 | mergeInfoList(infoList); 87 | view.loadComplete(entityList); 88 | } 89 | } 90 | 91 | public void mergeInfoList(List infoList) { 92 | entityList = new ArrayList<>(); 93 | for (EntityInfo entityInfo : infoList) { 94 | Entity entity; 95 | if (TmpData.contentCode == AppConstant.COMIC_CODE) { 96 | entity = new Comic((ComicInfo) entityInfo); 97 | } else if (TmpData.contentCode == AppConstant.READER_CODE) { 98 | entity = new Novel((NovelInfo) entityInfo); 99 | } else { 100 | entity = new Video((VideoInfo) entityInfo); 101 | } 102 | entityList.add(entity); 103 | } 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/presenter/ReaderPresenter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.presenter; 2 | 3 | import com.qc.common.ui.view.ReaderView; 4 | import com.qc.common.util.EntityHelper; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import io.reactivex.android.schedulers.AndroidSchedulers; 10 | import okhttp3.Request; 11 | import the.one.base.ui.presenter.BasePresenter; 12 | import top.luqichuang.common.model.ChapterInfo; 13 | import top.luqichuang.common.model.Content; 14 | import top.luqichuang.common.model.Entity; 15 | import top.luqichuang.common.model.Source; 16 | import top.luqichuang.common.self.CommonCallback; 17 | import top.luqichuang.common.util.NetUtil; 18 | 19 | /** 20 | * @author LuQiChuang 21 | * @desc 22 | * @date 2021/6/10 22:30 23 | * @ver 1.0 24 | */ 25 | public class ReaderPresenter extends BasePresenter { 26 | 27 | public void loadContentInfoList(Entity entity) { 28 | List chapterInfoList = entity.getInfo().getChapterInfoList(); 29 | int position = EntityHelper.getPosition(entity.getInfo()); 30 | int chapterId = entity.getInfo().getCurChapterId(); 31 | String url = chapterInfoList.get(position).getChapterUrl(); 32 | Source source = EntityHelper.commonSource(entity); 33 | Request request = source.getContentRequest(url); 34 | NetUtil.startLoad(new CommonCallback(request, source, Source.CONTENT) { 35 | @Override 36 | protected void initData(Map data) { 37 | super.initData(data); 38 | data.put("chapterId", chapterId); 39 | } 40 | 41 | @Override 42 | public void onFailure(String errorMsg) { 43 | ReaderView view = getView(); 44 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 45 | if (view != null) { 46 | view.loadReadContentComplete(null, errorMsg); 47 | } 48 | }); 49 | } 50 | 51 | @Override 52 | public void onResponse(String html, Map map) { 53 | ReaderView view = getView(); 54 | List list = EntityHelper.getContentList(entity, html, chapterId, map); 55 | if (list.isEmpty()) { 56 | onFailure("解析失败!"); 57 | } else { 58 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 59 | if (view != null) { 60 | view.loadReadContentComplete(list, null); 61 | } 62 | }); 63 | } 64 | } 65 | }); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/presenter/ShelfPresenter.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.presenter; 2 | 3 | import com.qc.common.ui.view.ShelfView; 4 | import com.qc.common.util.DBUtil; 5 | import com.qc.common.util.EntityHelper; 6 | import com.qc.common.util.EntityUtil; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import io.reactivex.android.schedulers.AndroidSchedulers; 12 | import okhttp3.Request; 13 | import the.one.base.ui.presenter.BasePresenter; 14 | import top.luqichuang.common.model.Entity; 15 | import top.luqichuang.common.model.EntityInfo; 16 | import top.luqichuang.common.model.Source; 17 | import top.luqichuang.common.self.CommonCallback; 18 | import top.luqichuang.common.util.NetUtil; 19 | 20 | /** 21 | * @author LuQiChuang 22 | * @desc 23 | * @date 2021/6/9 18:50 24 | * @ver 1.0 25 | */ 26 | public class ShelfPresenter extends BasePresenter { 27 | 28 | private boolean isAll = false; 29 | 30 | private int priority = 0; 31 | 32 | public void checkUpdate(List entityList) { 33 | for (Entity entity : entityList) { 34 | if (isAll) { 35 | for (EntityInfo info : entity.getInfoList()) { 36 | checkUpdate(entity, info); 37 | } 38 | } else { 39 | checkUpdate(entity, entity.getInfo()); 40 | } 41 | } 42 | } 43 | 44 | private void checkUpdate(Entity entity, EntityInfo info) { 45 | Source source = EntityHelper.commonSource(entity); 46 | Request request = source.getDetailRequest(info.getDetailUrl()); 47 | NetUtil.startLoad(new CommonCallback(request, source, null) { 48 | @Override 49 | public void onFailure(String errorMsg) { 50 | ShelfView view = getView(); 51 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 52 | if (view != null) { 53 | view.checkUpdateComplete(info.getTitle()); 54 | } 55 | }); 56 | } 57 | 58 | @Override 59 | public void onResponse(String html, Map map) { 60 | ShelfView view = getView(); 61 | AndroidSchedulers.mainThread().scheduleDirect(() -> { 62 | if (view != null) { 63 | String curUpdateChapter = info.getUpdateChapter(); 64 | source.setInfoDetail(info, html, map); 65 | if (curUpdateChapter == null || !curUpdateChapter.equals(info.getUpdateChapter())) { 66 | if (info.getUpdateChapter() != null) { 67 | entity.setUpdate(true); 68 | entity.setPriority(++priority); 69 | EntityUtil.first(entity); 70 | } 71 | } 72 | DBUtil.save(entity, DBUtil.SAVE_CUR); 73 | view.checkUpdateComplete(null); 74 | } 75 | }); 76 | } 77 | }); 78 | 79 | } 80 | 81 | public void initPriority() { 82 | this.priority = 0; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/view/ChapterView.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.view; 2 | 3 | import java.util.List; 4 | 5 | import the.one.base.ui.view.BaseView; 6 | import top.luqichuang.common.model.EntityInfo; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2020/8/12 15:25 12 | * @ver 1.0 13 | */ 14 | public interface ChapterView extends BaseView { 15 | 16 | void loadComplete(); 17 | 18 | void updateSourceComplete(List infoList); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/view/RankView.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.view; 2 | 3 | import java.util.List; 4 | 5 | import the.one.base.ui.view.BaseView; 6 | import top.luqichuang.common.model.Entity; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2020/8/12 15:25 12 | * @ver 1.0 13 | */ 14 | public interface RankView extends BaseView { 15 | 16 | void loadComplete(List entityList); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/view/ReaderView.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.view; 2 | 3 | import java.util.List; 4 | 5 | import the.one.base.ui.view.BaseView; 6 | import top.luqichuang.common.model.Content; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2020/8/12 15:25 12 | * @ver 1.0 13 | */ 14 | public interface ReaderView extends BaseView { 15 | 16 | void loadReadContentComplete(List contentList, String errorMsg); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/view/SearchView.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.view; 2 | 3 | import java.util.List; 4 | 5 | import the.one.base.ui.view.BaseView; 6 | import top.luqichuang.common.model.Entity; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2020/8/12 15:25 12 | * @ver 1.0 13 | */ 14 | public interface SearchView extends BaseView { 15 | 16 | void searchComplete(List entityList, String sourceName); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/view/ShelfView.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.view; 2 | 3 | import the.one.base.ui.view.BaseView; 4 | 5 | /** 6 | * @author LuQiChuang 7 | * @desc 8 | * @date 2020/8/12 15:25 9 | * @ver 1.0 10 | */ 11 | public interface ShelfView extends BaseView { 12 | 13 | void checkUpdateComplete(String title); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/ui/view/UpdateView.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.ui.view; 2 | 3 | import the.one.base.ui.view.BaseView; 4 | 5 | /** 6 | * @author LuQiChuang 7 | * @desc 8 | * @date 2020/8/12 15:25 9 | * @ver 1.0 10 | */ 11 | public interface UpdateView extends BaseView { 12 | 13 | void getVersionTag(String versionTag, String href); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/util/AnimationUtil.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.util; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.view.View; 5 | import android.view.animation.Animation; 6 | import android.widget.ImageView; 7 | 8 | import com.qmuiteam.qmui.util.QMUIViewHelper; 9 | 10 | import java.util.Objects; 11 | 12 | /** 13 | * @author LuQiChuang 14 | * @desc 15 | * @date 2021/2/28 21:54 16 | * @ver 1.0 17 | */ 18 | public class AnimationUtil { 19 | 20 | public static void changeDrawable(ImageView imageView, Drawable drawable) { 21 | changeDrawable(imageView, drawable, true); 22 | } 23 | 24 | public static void changeDrawable(ImageView imageView, Drawable drawable, boolean needAnimation) { 25 | if (needAnimation) { 26 | QMUIViewHelper.fadeOut(imageView, 200, new Animation.AnimationListener() { 27 | @Override 28 | public void onAnimationStart(Animation animation) { 29 | 30 | } 31 | 32 | @Override 33 | public void onAnimationEnd(Animation animation) { 34 | imageView.setImageDrawable(drawable); 35 | QMUIViewHelper.fadeIn(imageView, 200, null, true); 36 | } 37 | 38 | @Override 39 | public void onAnimationRepeat(Animation animation) { 40 | 41 | } 42 | }, true); 43 | } else { 44 | imageView.setImageDrawable(drawable); 45 | } 46 | } 47 | 48 | public static void changeViewVisibility(View view) { 49 | Object tag = initTag(view); 50 | if (Objects.equals(tag, View.VISIBLE)) { 51 | view.setTag(View.GONE); 52 | QMUIViewHelper.fadeOut(view, 300, null, true); 53 | } else { 54 | view.setTag(View.VISIBLE); 55 | QMUIViewHelper.fadeIn(view, 300, null, true); 56 | } 57 | } 58 | 59 | public static boolean changeViewVisibility(View view, boolean visible) { 60 | return changeViewVisibility(view, visible, null); 61 | } 62 | 63 | public static boolean changeViewVisibility(View view, boolean visible, Animation.AnimationListener listener) { 64 | Object tag = initTag(view); 65 | if (Objects.equals(tag, View.VISIBLE) && !visible) { 66 | view.setTag(View.GONE); 67 | QMUIViewHelper.fadeOut(view, 300, listener, true); 68 | return true; 69 | } else if (Objects.equals(tag, View.GONE) && visible) { 70 | view.setTag(View.VISIBLE); 71 | QMUIViewHelper.fadeIn(view, 300, listener, true); 72 | return true; 73 | } 74 | return false; 75 | } 76 | 77 | private static Object initTag(View view) { 78 | Object tag = view.getTag(); 79 | if (tag == null) { 80 | if (view.getVisibility() == View.VISIBLE) { 81 | view.setTag(View.VISIBLE); 82 | tag = View.VISIBLE; 83 | } else { 84 | view.setTag(View.GONE); 85 | tag = View.GONE; 86 | } 87 | } 88 | return tag; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/util/PermissionUtil.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.util; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.view.inputmethod.InputMethodManager; 8 | 9 | import androidx.core.app.ActivityCompat; 10 | 11 | import the.one.base.widge.TheSearchView; 12 | 13 | /** 14 | * @author LuQiChuang 15 | * @desc 16 | * @date 2020/8/12 15:25 17 | * @ver 1.0 18 | */ 19 | public class PermissionUtil { 20 | 21 | private static final int REQUEST_EXTERNAL_STORAGE = 1; 22 | private static String[] PERMISSIONS_STORAGE = { 23 | Manifest.permission.READ_EXTERNAL_STORAGE, 24 | Manifest.permission.WRITE_EXTERNAL_STORAGE 25 | }; 26 | 27 | public static void verifyStoragePermissions(Activity activity) { 28 | int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); 29 | if (permission != PackageManager.PERMISSION_GRANTED) { 30 | ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); 31 | } 32 | } 33 | 34 | public static void hiddenKeyBoard(TheSearchView searchView) { 35 | InputMethodManager inputMethodManager = (InputMethodManager) searchView.getContext().getApplicationContext(). 36 | getSystemService(Context.INPUT_METHOD_SERVICE); 37 | if (inputMethodManager != null) { 38 | inputMethodManager.hideSoftInputFromWindow(searchView.getWindowToken(), 0); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/util/PopupUtil.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.util; 2 | 3 | import android.content.Context; 4 | 5 | import com.qc.common.constant.AppConstant; 6 | import com.qc.common.constant.TmpData; 7 | import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet; 8 | 9 | import java.util.ArrayList; 10 | import java.util.LinkedHashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import the.one.base.model.PopupItem; 15 | import the.one.base.util.QMUIBottomSheetUtil; 16 | import top.luqichuang.common.model.Entity; 17 | import top.luqichuang.common.model.EntityInfo; 18 | import top.luqichuang.common.util.MapUtil; 19 | import top.luqichuang.common.util.SourceUtil; 20 | 21 | /** 22 | * @author LuQiChuang 23 | * @version 1.0 24 | * @desc 25 | * @date 2020/8/12 21:33 26 | */ 27 | public class PopupUtil { 28 | 29 | public static List getPopupItemList(Map map) { 30 | List itemList = new ArrayList<>(); 31 | for (String value : map.values()) { 32 | itemList.add(new PopupItem(value)); 33 | } 34 | return itemList; 35 | } 36 | 37 | public static String getKey(Entity entity) { 38 | return getKey(entity.getInfo()); 39 | } 40 | 41 | public static String getKey(EntityInfo info) { 42 | return info.getId() + "#" + info.getSourceId() + "#" + info.getAuthor(); 43 | } 44 | 45 | public static int getIdByKey(String key) { 46 | return Integer.parseInt(key.split("#")[0]); 47 | } 48 | 49 | public static Map getMap(List infoList) { 50 | Map map = new LinkedHashMap<>(); 51 | for (EntityInfo info : infoList) { 52 | if (TmpData.contentCode == AppConstant.COMIC_CODE) { 53 | map.put(getKey(info), SourceUtil.getSourceName(info.getSourceId())); 54 | } else if (TmpData.contentCode == AppConstant.READER_CODE) { 55 | map.put(getKey(info), SourceUtil.getNSourceName(info.getSourceId()) + '-' + info.getAuthor()); 56 | } else { 57 | map.put(getKey(info), SourceUtil.getVSourceName(info.getSourceId())); 58 | } 59 | } 60 | return map; 61 | } 62 | 63 | public static void showSimpleBottomSheetList(Context context, Map map, Object key, String title, QMUIBottomSheet.BottomListSheetBuilder.OnSheetItemClickListener listener) { 64 | List list = getPopupItemList(map); 65 | int index = MapUtil.indexOf(map, key); 66 | QMUIBottomSheetUtil.showSimpleBottomSheetList(context, list, title, index, listener).show(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/util/RestartUtil.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | 6 | import com.qc.common.ui.activity.LauncherActivity; 7 | import com.qc.common.ui.activity.MainActivity; 8 | 9 | /** 10 | * @author LuQiChuang 11 | * @desc 重启工具 12 | * @date 2020/8/18 10:02 13 | * @ver 1.0 14 | */ 15 | public class RestartUtil { 16 | 17 | private static void restart(Activity activity) { 18 | Intent intent = new Intent(activity, LauncherActivity.class); 19 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 20 | intent.setAction(Intent.ACTION_MAIN); 21 | intent.addCategory(Intent.CATEGORY_LAUNCHER); 22 | activity.finish(); 23 | activity.startActivity(intent); 24 | // android.os.Process.killProcess(android.os.Process.myPid()); 25 | } 26 | 27 | public static void restart() { 28 | restart(MainActivity.getInstance()); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/util/SettingItemUtil.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.util; 2 | 3 | import com.qc.common.constant.AppConstant; 4 | import com.qc.common.en.SettingEnum; 5 | 6 | import java.util.LinkedHashMap; 7 | import java.util.Map; 8 | 9 | import top.luqichuang.common.model.Source; 10 | import top.luqichuang.common.util.MapUtil; 11 | import top.luqichuang.common.util.SourceUtil; 12 | import top.luqichuang.mycomic.model.ComicInfo; 13 | import top.luqichuang.mynovel.model.NovelInfo; 14 | import top.luqichuang.myvideo.model.VideoInfo; 15 | 16 | /** 17 | * @author LuQiChuang 18 | * @desc 19 | * @date 2021/1/16 23:36 20 | * @ver 1.0 21 | */ 22 | public class SettingItemUtil { 23 | 24 | public static Map getMap(SettingEnum settingEnum) { 25 | Map map = new LinkedHashMap<>(); 26 | if (settingEnum == SettingEnum.DEFAULT_SOURCE) { 27 | for (Source source : SourceUtil.getSourceList()) { 28 | map.put(source.getSourceId(), source.getSourceName()); 29 | } 30 | } else if (settingEnum == SettingEnum.DEFAULT_NOVEL_SOURCE) { 31 | for (Source source : SourceUtil.getNSourceList()) { 32 | map.put(source.getSourceId(), source.getSourceName()); 33 | } 34 | } else if (settingEnum == SettingEnum.DEFAULT_VIDEO_SOURCE) { 35 | for (Source source : SourceUtil.getVSourceList()) { 36 | map.put(source.getSourceId(), source.getSourceName()); 37 | } 38 | } else if (settingEnum == SettingEnum.PRELOAD_NUM) { 39 | map.put(0, "关闭预加载"); 40 | map.put(5, "预加载5页"); 41 | map.put(10, "预加载10页"); 42 | map.put(10000, "预加载所有"); 43 | } else if (settingEnum == SettingEnum.READ_CONTENT) { 44 | map.put(AppConstant.COMIC_CODE, "漫画"); 45 | map.put(AppConstant.READER_CODE, "小说"); 46 | map.put(AppConstant.VIDEO_CODE, "番剧"); 47 | } 48 | return map; 49 | } 50 | 51 | public static Object getDefaultKey(SettingEnum settingEnum) { 52 | Map map = getMap(settingEnum); 53 | if (!map.isEmpty()) { 54 | return MapUtil.getFirst(map).getKey(); 55 | } 56 | return ""; 57 | } 58 | 59 | public static String getDefaultDesc(SettingEnum settingEnum) { 60 | Map map = getMap(settingEnum); 61 | if (!map.isEmpty()) { 62 | return map.get(settingEnum.DEFAULT_VALUE); 63 | } 64 | return ""; 65 | } 66 | 67 | public static String getDesc(SettingEnum settingEnum, Object key) { 68 | Map map = getMap(settingEnum); 69 | return getDesc(map, key); 70 | } 71 | 72 | public static String getDesc(Map map, Object key) { 73 | if (!map.isEmpty()) { 74 | return map.get(key); 75 | } 76 | return ""; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/util/SettingUtil.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.util; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.qc.common.en.SettingEnum; 5 | 6 | import the.one.base.util.SpUtil; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2021/1/16 21:39 12 | * @ver 1.0 13 | */ 14 | public class SettingUtil { 15 | 16 | private static final JSONObject JSON_OBJECT; 17 | 18 | private static final String SAVE_STR = "json"; 19 | 20 | static { 21 | JSON_OBJECT = JSONObject.parseObject(getData()); 22 | } 23 | 24 | private static String getData() { 25 | // SpUtil.getInstance().putString(SAVE_STR, "{}"); 26 | return SpUtil.getInstance().getString(SAVE_STR, "{}"); 27 | } 28 | 29 | private static void save() { 30 | SpUtil.getInstance().putString(SAVE_STR, JSON_OBJECT.toJSONString()); 31 | } 32 | 33 | public static Object getSettingKey(SettingEnum settingEnum) { 34 | Object key = JSON_OBJECT.get(settingEnum.KEY); 35 | if (key == null) { 36 | key = settingEnum.DEFAULT_VALUE; 37 | JSON_OBJECT.put(settingEnum.KEY, settingEnum.DEFAULT_VALUE); 38 | save(); 39 | } 40 | return key; 41 | } 42 | 43 | public static String getSettingDesc(SettingEnum settingEnum) { 44 | String desc = (String) JSON_OBJECT.get(settingEnum.KEY + "Desc"); 45 | if (desc == null) { 46 | desc = SettingItemUtil.getDefaultDesc(settingEnum); 47 | } 48 | return desc; 49 | } 50 | 51 | public static void putSetting(SettingEnum settingEnum, Object value) { 52 | putSetting(settingEnum, value, ""); 53 | } 54 | 55 | public static void putSetting(SettingEnum settingEnum, Object value, String desc) { 56 | JSON_OBJECT.put(settingEnum.KEY, value); 57 | JSON_OBJECT.put(settingEnum.KEY + "Desc", desc); 58 | save(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/qc/common/util/VersionUtil.java: -------------------------------------------------------------------------------- 1 | package com.qc.common.util; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageInfo; 6 | import android.content.pm.PackageManager; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 版本工具,获得版本名、版本号等信息 11 | * @date 2020/8/12 15:25 12 | * @ver 1.0 13 | */ 14 | public class VersionUtil { 15 | 16 | public static String versionName; 17 | 18 | public static int versionCode; 19 | 20 | public static String appName; 21 | 22 | public static void initVersion(Context context) { 23 | versionName = getVersionName(context); 24 | versionCode = getVersionCode(context); 25 | appName = getAppName(context); 26 | } 27 | 28 | /** 29 | * 获取版本名称 30 | * 31 | * @param context context 32 | * @return String 版本名称 33 | */ 34 | public static String getVersionName(Context context) { 35 | 36 | //获取包管理器 37 | PackageManager pm = context.getPackageManager(); 38 | //获取包信息 39 | try { 40 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 41 | //返回版本号 42 | return packageInfo.versionName; 43 | } catch (PackageManager.NameNotFoundException e) { 44 | e.printStackTrace(); 45 | } 46 | 47 | return null; 48 | 49 | } 50 | 51 | /** 52 | * 获取版本号 53 | * 54 | * @param context 上下文 55 | * @return 版本号 56 | */ 57 | public static int getVersionCode(Context context) { 58 | 59 | //获取包管理器 60 | PackageManager pm = context.getPackageManager(); 61 | //获取包信息 62 | try { 63 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 64 | //返回版本号 65 | return packageInfo.versionCode; 66 | } catch (PackageManager.NameNotFoundException e) { 67 | e.printStackTrace(); 68 | } 69 | 70 | return 0; 71 | 72 | } 73 | 74 | /** 75 | * 获取App的名称 76 | * 77 | * @param context 上下文 78 | * @return 名称 79 | */ 80 | public static String getAppName(Context context) { 81 | PackageManager pm = context.getPackageManager(); 82 | //获取包信息 83 | try { 84 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 85 | //获取应用 信息 86 | ApplicationInfo applicationInfo = packageInfo.applicationInfo; 87 | //获取albelRes 88 | int labelRes = applicationInfo.labelRes; 89 | //返回App的名称 90 | return context.getResources().getString(labelRes); 91 | } catch (PackageManager.NameNotFoundException e) { 92 | e.printStackTrace(); 93 | } 94 | 95 | return null; 96 | } 97 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/drawable/head.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_brightness_1_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_brightness_2_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_check_circle_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_favorite_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_favorite_border_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_home_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_home_select_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_image_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_image_search_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_keyboard_arrow_left_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_keyboard_arrow_right_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_list_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_menu_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_person_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_person_select_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_search_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_search_select_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_settings_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_swap_vert_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_turned_in_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_error_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/drawable/ic_image_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_reader_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_reader_error_foreground.xml: -------------------------------------------------------------------------------- 1 | 8 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_reader_loading_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_shelf_error_foreground.xml: -------------------------------------------------------------------------------- 1 | 8 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image_shelf_loading_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/drawable/ic_text.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_text_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/drawable/ic_text_black.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_text_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/drawable/ic_text_blue.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_video.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_person.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_rank_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_reader_display.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 17 | 18 | 27 | 28 | 36 | 37 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_reader_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 23 | 24 | 35 | 36 | 40 | 41 | 46 | 47 | 56 | 57 | 58 | 59 | 62 | 63 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_reader_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 11 | 12 | 17 | 18 | 19 | 20 | 35 | 36 | 41 | 42 | 49 | 50 | 54 | 55 | 56 | 57 | 62 | 63 | 68 | 69 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_search_result.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_shelf.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_shelf_collect.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_shelf_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_chapter.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_rank_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_rank_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 37 | 38 | 44 | 45 | 46 | 47 | 48 | 49 | 53 | 54 | 61 | 62 | 68 | 69 | 72 | 73 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_rank_right_simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 20 | 21 | 29 | 30 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 54 | 55 | 62 | 63 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_reader.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_reader_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_reader_novel.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 17 | 18 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 36 | 37 | 43 | 44 | 50 | 51 | 54 | 55 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/left_rank.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/module_image_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 20 | 21 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/module_image_reader.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/module_image_shelf.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/top_person.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/viewpager_chapter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #03A9F4 4 | #2196F3 5 | #02D0E6 6 | #FFFFFF 7 | #000000 8 | #808080 9 | #E3E3E3 10 | #F44336 11 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MyComic 3 | 4 | defaultSourceId 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 16 | 17 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/test/java/com/qc/mycomic/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.qc.mycomic; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | mavenCentral() 5 | maven { url 'https://maven.aliyun.com/repository/releases' } 6 | maven { url 'https://jitpack.io' } 7 | google() 8 | jcenter() 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:4.1.2' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | mavenCentral() 21 | maven { url 'https://maven.aliyun.com/repository/releases' } 22 | maven { url 'https://jitpack.io' } 23 | google() 24 | jcenter() 25 | } 26 | } 27 | 28 | task clean(type: Delete) { 29 | delete rootProject.buildDir 30 | } -------------------------------------------------------------------------------- /common/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.3" 8 | 9 | defaultConfig { 10 | minSdkVersion 21 11 | targetSdkVersion 29 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | consumerProguardFiles "consumer-rules.pro" 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | compileOptions { 26 | sourceCompatibility JavaVersion.VERSION_1_8 27 | targetCompatibility JavaVersion.VERSION_1_8 28 | } 29 | lintOptions { 30 | abortOnError false 31 | } 32 | } 33 | 34 | //task makeJar(type: Copy) { 35 | // delete 'build/libs/MyComic.jar' 36 | // from('build/intermediates/aar_main_jar/release/') 37 | //// from(project.zipTree('')) 38 | // into('build/libs/') 39 | // include('classes.jar') 40 | // include(project.zipTree('libs-build\\litepal-core-3.0.0.jar')) 41 | // rename('classes.jar', 'MyReader.jar') 42 | //} 43 | ////执行 44 | //makeJar.dependsOn(build) 45 | 46 | task makeJar(type: Jar) { 47 | archiveName('MyReader.jar') 48 | from(project.zipTree('build/intermediates/aar_main_jar/release/classes.jar')) 49 | from(project.zipTree('libs-build\\litepal-core-3.0.0.jar')) 50 | from(project.zipTree('libs-build\\okhttp-3.14.4.jar')) 51 | from(project.zipTree('libs-build\\rhino-1.7.13.jar')) 52 | from(project.zipTree('libs-build\\okio-2.5.0.jar')) 53 | from(project.zipTree('libs-build\\kotlin-stdlib-1.3.72.jar')) 54 | destinationDir(file('libs-build\\libs')) 55 | } 56 | makeJar.dependsOn(build) 57 | 58 | dependencies { 59 | api fileTree(dir: "libs", include: ["*.jar"]) 60 | api 'com.gitee.theoneee:TheBase:2.0.2' 61 | api 'org.litepal.android:java:3.0.0' 62 | api 'com.alibaba:fastjson:1.2.75' 63 | api 'org.mozilla:rhino:1.7.13' 64 | api 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer:v8.1.5-jitpack' 65 | api 'androidx.appcompat:appcompat:1.2.0' 66 | api 'junit:junit:4.13.2' 67 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 68 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 69 | } -------------------------------------------------------------------------------- /common/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/common/consumer-rules.pro -------------------------------------------------------------------------------- /common/libs-build/fastjson-1.2.75.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/common/libs-build/fastjson-1.2.75.jar -------------------------------------------------------------------------------- /common/libs-build/kotlin-stdlib-1.3.72.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/common/libs-build/kotlin-stdlib-1.3.72.jar -------------------------------------------------------------------------------- /common/libs-build/litepal-core-3.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/common/libs-build/litepal-core-3.0.0.jar -------------------------------------------------------------------------------- /common/libs-build/okhttp-3.14.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/common/libs-build/okhttp-3.14.4.jar -------------------------------------------------------------------------------- /common/libs-build/okio-2.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/common/libs-build/okio-2.5.0.jar -------------------------------------------------------------------------------- /common/libs-build/rhino-1.7.13.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/common/libs-build/rhino-1.7.13.jar -------------------------------------------------------------------------------- /common/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/en/NSourceEnum.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.en; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | import top.luqichuang.common.model.Source; 7 | import top.luqichuang.mynovel.model.NovelInfo; 8 | import top.luqichuang.mynovel.source.AiYue; 9 | import top.luqichuang.mynovel.source.K17; 10 | import top.luqichuang.mynovel.source.MiKanShu; 11 | import top.luqichuang.mynovel.source.MoYuan; 12 | import top.luqichuang.mynovel.source.ShuBen; 13 | import top.luqichuang.mynovel.source.TaDu; 14 | import top.luqichuang.mynovel.source.XiaoShuoE; 15 | import top.luqichuang.mynovel.source.XinBiQuGe; 16 | import top.luqichuang.mynovel.source.XinBiQuGe2; 17 | import top.luqichuang.mynovel.source.XuanShu; 18 | 19 | /** 20 | * @author LuQiChuang 21 | * @desc 22 | * @date 2021/1/11 23:51 23 | * @ver 1.0 24 | */ 25 | public enum NSourceEnum { 26 | XIN_BI_QU_GE(1, "新笔趣阁"), 27 | // QUAN_SHU(2, "全书网"), 28 | // QUAN_XIAO_SHUO(3, "全小说"), 29 | AI_YUE(4, "爱阅小说"), 30 | XUAN_SHU(5, "炫书网"), 31 | K17(6, "17K小说"), 32 | XIAO_SHUO_E(7, "E小说"), 33 | MO_YUAN(8, "墨缘文学"), 34 | MI_KAN_SHU(9, "Mi看书"), 35 | XIN_BI_QU_GE_2(10, "新笔趣阁[2]"), 36 | SHU_BEN(11, "书本网"), 37 | TA_DU(12, "塔读文学"), 38 | ; 39 | 40 | private static final Map> MAP = new LinkedHashMap<>(); 41 | 42 | static { 43 | MAP.put(XIN_BI_QU_GE.ID, new XinBiQuGe()); 44 | // MAP.put(QUAN_SHU.ID, new QuanShu()); 45 | // MAP.put(QUAN_XIAO_SHUO.ID, new QuanXiaoShuo()); 46 | MAP.put(AI_YUE.ID, new AiYue()); 47 | MAP.put(XUAN_SHU.ID, new XuanShu()); 48 | MAP.put(K17.ID, new K17()); 49 | MAP.put(XIAO_SHUO_E.ID, new XiaoShuoE()); 50 | MAP.put(MO_YUAN.ID, new MoYuan()); 51 | MAP.put(MI_KAN_SHU.ID, new MiKanShu()); 52 | MAP.put(XIN_BI_QU_GE_2.ID, new XinBiQuGe2()); 53 | MAP.put(SHU_BEN.ID, new ShuBen()); 54 | MAP.put(TA_DU.ID, new TaDu()); 55 | } 56 | 57 | public static Map> getMAP() { 58 | return MAP; 59 | } 60 | 61 | public final int ID; 62 | public final String NAME; 63 | 64 | NSourceEnum(int id, String name) { 65 | this.ID = id; 66 | this.NAME = name; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/en/SourceEnum.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.en; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | import top.luqichuang.common.model.Source; 7 | import top.luqichuang.mycomic.model.ComicInfo; 8 | import top.luqichuang.mycomic.source.AiYouMan; 9 | import top.luqichuang.mycomic.source.BL; 10 | import top.luqichuang.mycomic.source.BaoZi; 11 | import top.luqichuang.mycomic.source.BiliBili; 12 | import top.luqichuang.mycomic.source.DaShu; 13 | import top.luqichuang.mycomic.source.Du; 14 | import top.luqichuang.mycomic.source.MH118; 15 | import top.luqichuang.mycomic.source.MH118W; 16 | import top.luqichuang.mycomic.source.MH1234; 17 | import top.luqichuang.mycomic.source.ManHuaTai; 18 | import top.luqichuang.mycomic.source.MiTui; 19 | import top.luqichuang.mycomic.source.OH; 20 | import top.luqichuang.mycomic.source.PuFei; 21 | import top.luqichuang.mycomic.source.QiMiao; 22 | import top.luqichuang.mycomic.source.SiSi; 23 | import top.luqichuang.mycomic.source.TengXun; 24 | 25 | /** 26 | * @author LuQiChuang 27 | * @desc 28 | * @date 2021/1/11 23:51 29 | * @ver 1.0 30 | */ 31 | public enum SourceEnum { 32 | MI_TUI(1, "米推漫画"), 33 | // MAN_HUA_FEN(2, "漫画粉"), 34 | PU_FEI(3, "扑飞漫画"), 35 | TENG_XUN(4, "腾讯动漫"), 36 | BILI_BILI(5, "哔哩哔哩"), 37 | OH(6, "OH漫画"), 38 | MAN_HUA_TAI(7, "漫画台"), 39 | MH_118(8, "118漫画"), 40 | DU(9, "独漫画"), 41 | BL(10, "BL漫画"), 42 | AI_YOU_MAN(11, "爱优漫"), 43 | MH_1234(12, "1234漫画"), 44 | MH_118_2(13, "118漫画[2]"), 45 | QI_MIAO(14, "奇妙漫画"), 46 | DA_SHU(15, "大树漫画"), 47 | SI_SI(16, "思思漫画"), 48 | BAO_ZI(17, "包子漫画"), 49 | ; 50 | 51 | private static final Map> MAP = new LinkedHashMap<>(); 52 | 53 | static { 54 | MAP.put(MI_TUI.ID, new MiTui()); 55 | // MAP.put(MAN_HUA_FEN.ID, new ManHuaFen()); 56 | MAP.put(PU_FEI.ID, new PuFei()); 57 | MAP.put(TENG_XUN.ID, new TengXun()); 58 | MAP.put(BILI_BILI.ID, new BiliBili()); 59 | MAP.put(OH.ID, new OH()); 60 | MAP.put(MAN_HUA_TAI.ID, new ManHuaTai()); 61 | MAP.put(MH_118.ID, new MH118()); 62 | MAP.put(DU.ID, new Du()); 63 | MAP.put(BL.ID, new BL()); 64 | MAP.put(AI_YOU_MAN.ID, new AiYouMan()); 65 | MAP.put(MH_1234.ID, new MH1234()); 66 | MAP.put(MH_118_2.ID, new MH118W()); 67 | MAP.put(QI_MIAO.ID, new QiMiao()); 68 | MAP.put(DA_SHU.ID, new DaShu()); 69 | MAP.put(SI_SI.ID, new SiSi()); 70 | MAP.put(BAO_ZI.ID, new BaoZi()); 71 | } 72 | 73 | public static Map> getMAP() { 74 | return MAP; 75 | } 76 | 77 | public final int ID; 78 | public final String NAME; 79 | 80 | SourceEnum(int id, String name) { 81 | this.ID = id; 82 | this.NAME = name; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/en/VSourceEnum.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.en; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | import top.luqichuang.common.model.Source; 7 | import top.luqichuang.myvideo.model.VideoInfo; 8 | import top.luqichuang.myvideo.source.AiYun; 9 | import top.luqichuang.myvideo.source.BiliBili; 10 | import top.luqichuang.myvideo.source.FengChe; 11 | import top.luqichuang.myvideo.source.FengChe2; 12 | import top.luqichuang.myvideo.source.MiLiMiLi; 13 | import top.luqichuang.myvideo.source.YingHua; 14 | import top.luqichuang.myvideo.source.YingHua2; 15 | 16 | /** 17 | * @author LuQiChuang 18 | * @desc 19 | * @date 2021/6/22 23:47 20 | * @ver 1.0 21 | */ 22 | public enum VSourceEnum { 23 | YING_HUA(1, "樱花动漫"), 24 | MILI_MILI(2, "米粒米粒"), 25 | FENG_CHE(3, "风车动漫"), 26 | YING_HUA_2(4, "樱花动漫[2]"), 27 | BILI_BILI(5, "哔哩哔哩"), 28 | FENG_CHE_2(6, "风车动漫[2]"), 29 | AI_YUN(7, "爱云影视"), 30 | ; 31 | 32 | private static final Map> MAP = new LinkedHashMap<>(); 33 | 34 | static { 35 | MAP.put(YING_HUA.ID, new YingHua()); 36 | MAP.put(MILI_MILI.ID, new MiLiMiLi()); 37 | MAP.put(FENG_CHE.ID, new FengChe()); 38 | MAP.put(YING_HUA_2.ID, new YingHua2()); 39 | MAP.put(BILI_BILI.ID, new BiliBili()); 40 | MAP.put(FENG_CHE_2.ID, new FengChe2()); 41 | MAP.put(AI_YUN.ID, new AiYun()); 42 | } 43 | 44 | public static Map> getMAP() { 45 | return MAP; 46 | } 47 | 48 | public final int ID; 49 | public final String NAME; 50 | 51 | VSourceEnum(int id, String name) { 52 | this.ID = id; 53 | this.NAME = name; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/json/JsonNode.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.json; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.alibaba.fastjson.JSONObject; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | /** 10 | * @author LuQiChuang 11 | * @desc 12 | * @date 2020/8/12 15:27 13 | * @ver 1.0 14 | */ 15 | public class JsonNode { 16 | 17 | private JSONObject jsonObject; 18 | 19 | public JsonNode() { 20 | } 21 | 22 | public JsonNode(JSONObject jsonObject) { 23 | init(jsonObject); 24 | } 25 | 26 | public JsonNode(String json) { 27 | init(json); 28 | } 29 | 30 | public JsonNode(String json, String... conditions) { 31 | init(json); 32 | initConditions(conditions); 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "JsonNode{" + 38 | "jsonObject=" + jsonObject + 39 | '}'; 40 | } 41 | 42 | private JSONObject parse(String json) { 43 | return JSONObject.parseObject(json); 44 | } 45 | 46 | public void init(JSONObject jsonObject) { 47 | this.jsonObject = jsonObject; 48 | } 49 | 50 | public void init(String json) { 51 | try { 52 | this.jsonObject = parse(json); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | public void initConditions(String... conditions) { 59 | try { 60 | for (String condition : conditions) { 61 | init(jsonObject(condition)); 62 | } 63 | } catch (Exception e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | 68 | public Set keySet() { 69 | try { 70 | return jsonObject.keySet(); 71 | } catch (Exception e) { 72 | return new HashSet<>(); 73 | } 74 | } 75 | 76 | public String arrayToString(String key) { 77 | try { 78 | String string = jsonObject.getJSONArray(key).toString(); 79 | string = string.replace("[", "").replace("]", "").replace("\"", ""); 80 | return string; 81 | } catch (Exception e) { 82 | return null; 83 | } 84 | } 85 | 86 | public String string(String key) { 87 | try { 88 | return jsonObject.getString(key); 89 | } catch (Exception e) { 90 | return null; 91 | } 92 | } 93 | 94 | public JSONObject jsonObject(String key) { 95 | try { 96 | return jsonObject.getJSONObject(key); 97 | } catch (Exception e) { 98 | return null; 99 | } 100 | } 101 | 102 | public JSONArray jsonArray(String key) { 103 | try { 104 | return jsonObject.getJSONArray(key); 105 | } catch (Exception e) { 106 | return null; 107 | } 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/json/JsonStarter.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.json; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.alibaba.fastjson.JSONObject; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import top.luqichuang.common.util.StringUtil; 10 | 11 | /** 12 | * @author LuQiChuang 13 | * @desc 14 | * @date 2020/8/12 15:25 15 | * @ver 1.0 16 | */ 17 | public abstract class JsonStarter { 18 | 19 | private JsonNode node = new JsonNode(); 20 | 21 | private int cur; 22 | 23 | private int total; 24 | 25 | protected boolean isDESC() { 26 | return true; 27 | } 28 | 29 | public int getCur() { 30 | return cur; 31 | } 32 | 33 | public int getTotal() { 34 | return total; 35 | } 36 | 37 | private int getId(int i, int size) { 38 | if (isDESC()) { 39 | return size - i - 1; 40 | } else { 41 | return i; 42 | } 43 | } 44 | 45 | public List startDataList(String json, String... conditions) { 46 | node.init(json); 47 | JSONArray jsonArray = null; 48 | int i = 0; 49 | for (String condition : conditions) { 50 | if (++i != conditions.length) { 51 | node.init(node.jsonObject(condition)); 52 | } else { 53 | jsonArray = node.jsonArray(condition); 54 | } 55 | } 56 | return startDataList(jsonArray); 57 | } 58 | 59 | public List startDataList(JSONArray jsonArray) { 60 | List list = new ArrayList<>(); 61 | if (jsonArray != null) { 62 | total = jsonArray.size(); 63 | cur = 0; 64 | for (Object o : jsonArray) { 65 | JSONObject jsonObject = (JSONObject) o; 66 | node.init(jsonObject); 67 | int chapterId = getId(cur, total); 68 | T t = dealDataList(node, chapterId); 69 | cur++; 70 | if (t != null) { 71 | list.add(t); 72 | } 73 | } 74 | if (!isDESC()) { 75 | StringUtil.swapList(list); 76 | } 77 | } 78 | return list; 79 | } 80 | 81 | public void startData(String json, String... conditions) { 82 | node.init(json); 83 | node.initConditions(conditions); 84 | dealData(node); 85 | } 86 | 87 | protected void dealData(JsonNode node) { 88 | 89 | } 90 | 91 | protected T dealDataList(JsonNode node, int dataId) { 92 | return null; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/jsoup/JsoupStarter.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.jsoup; 2 | 3 | import top.luqichuang.common.util.StringUtil; 4 | 5 | import org.jsoup.nodes.Element; 6 | import org.jsoup.select.Elements; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * @author LuQiChuang 13 | * @desc 14 | * @date 2020/8/12 15:25 15 | * @ver 1.0 16 | */ 17 | public class JsoupStarter { 18 | 19 | private JsoupNode node = new JsoupNode(); 20 | 21 | private int size; 22 | 23 | protected boolean isDESC() { 24 | return true; 25 | } 26 | 27 | protected int getSize() { 28 | return size; 29 | } 30 | 31 | public final void startInfo(String html) { 32 | node.init(html); 33 | dealInfo(node); 34 | } 35 | 36 | public final List startElements(String html, String... cssQuery) { 37 | node.init(html); 38 | List list = new ArrayList<>(); 39 | Elements elements = null; 40 | for (String s : cssQuery) { 41 | elements = node.getElements(s); 42 | if (!elements.isEmpty()) { 43 | break; 44 | } 45 | } 46 | if (elements == null) { 47 | return list; 48 | } 49 | int i = 0; 50 | size = elements.size(); 51 | for (Element element : elements) { 52 | node.init(element); 53 | int chapterId = getId(i++, size); 54 | T t = dealElement(node, chapterId); 55 | if (t != null) { 56 | list.add(t); 57 | } 58 | } 59 | if (!isDESC()) { 60 | StringUtil.swapList(list); 61 | } 62 | return list; 63 | } 64 | 65 | protected void dealInfo(JsoupNode node) { 66 | } 67 | 68 | protected T dealElement(JsoupNode node, int elementId) { 69 | return null; 70 | } 71 | 72 | private int getId(int i, int size) { 73 | if (isDESC()) { 74 | return size - i - 1; 75 | } else { 76 | return i; 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/model/ChapterInfo.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author LuQiChuang 7 | * @desc 8 | * @date 2020/8/12 15:27 9 | * @ver 1.0 10 | */ 11 | public class ChapterInfo implements Serializable { 12 | 13 | private int id; 14 | 15 | private String title; 16 | 17 | private String chapterUrl; 18 | 19 | private int status; 20 | 21 | public ChapterInfo() { 22 | } 23 | 24 | public ChapterInfo(int id, String title, String chapterUrl) { 25 | this.id = id; 26 | this.title = title; 27 | this.chapterUrl = chapterUrl; 28 | } 29 | 30 | public ChapterInfo(String title, String chapterUrl) { 31 | this.title = title; 32 | this.chapterUrl = chapterUrl; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "ChapterInfo{" + 38 | "id=" + id + 39 | ", title='" + title + '\'' + 40 | ", chapterUrl='" + chapterUrl + '\'' + 41 | ", status=" + status + 42 | '}'; 43 | } 44 | 45 | public int getId() { 46 | return id; 47 | } 48 | 49 | public void setId(int id) { 50 | this.id = id; 51 | } 52 | 53 | public String getTitle() { 54 | return title; 55 | } 56 | 57 | public void setTitle(String title) { 58 | this.title = title; 59 | } 60 | 61 | public String getChapterUrl() { 62 | return chapterUrl; 63 | } 64 | 65 | public void setChapterUrl(String chapterUrl) { 66 | this.chapterUrl = chapterUrl; 67 | } 68 | 69 | public int getStatus() { 70 | return status; 71 | } 72 | 73 | public void setStatus(int status) { 74 | this.status = status; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/model/Content.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.model; 2 | 3 | import java.io.Serializable; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * @author LuQiChuang 9 | * @desc 10 | * @date 2021/6/11 9:15 11 | * @ver 1.0 12 | */ 13 | public class Content implements Serializable { 14 | 15 | private int id; 16 | 17 | private int chapterId; 18 | 19 | private int cur; 20 | 21 | private int total; 22 | 23 | private String url; 24 | 25 | private String content; 26 | 27 | private Map headerMap = new HashMap<>(); 28 | 29 | private int status; 30 | 31 | public Content() { 32 | } 33 | 34 | public Content(int chapterId) { 35 | this.chapterId = chapterId; 36 | this.cur = 1; 37 | this.total = 1; 38 | } 39 | 40 | public Content(int chapterId, String content) { 41 | this.chapterId = chapterId; 42 | this.content = content; 43 | } 44 | 45 | public Content(int chapterId, int cur, int total, String url) { 46 | this.chapterId = chapterId; 47 | this.cur = cur; 48 | this.total = total; 49 | this.url = url; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "Content{" + 55 | "id=" + id + 56 | ", chapterId=" + chapterId + 57 | ", url='" + url + '\'' + 58 | ", content='" + content + '\'' + 59 | ", cur=" + cur + 60 | ", total=" + total + 61 | ", status=" + status + 62 | '}'; 63 | } 64 | 65 | public int getId() { 66 | return id; 67 | } 68 | 69 | public void setId(int id) { 70 | this.id = id; 71 | } 72 | 73 | public int getChapterId() { 74 | return chapterId; 75 | } 76 | 77 | public void setChapterId(int chapterId) { 78 | this.chapterId = chapterId; 79 | } 80 | 81 | public int getCur() { 82 | return cur; 83 | } 84 | 85 | public void setCur(int cur) { 86 | this.cur = cur; 87 | } 88 | 89 | public int getTotal() { 90 | return total; 91 | } 92 | 93 | public void setTotal(int total) { 94 | this.total = total; 95 | } 96 | 97 | public String getUrl() { 98 | return url; 99 | } 100 | 101 | public void setUrl(String url) { 102 | this.url = url; 103 | } 104 | 105 | public String getContent() { 106 | return content; 107 | } 108 | 109 | public void setContent(String content) { 110 | this.content = content; 111 | } 112 | 113 | public Map getHeaderMap() { 114 | return headerMap; 115 | } 116 | 117 | public void setHeaderMap(Map headerMap) { 118 | this.headerMap = headerMap; 119 | } 120 | 121 | public int getStatus() { 122 | return status; 123 | } 124 | 125 | public void setStatus(int status) { 126 | this.status = status; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/model/Entity.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.model; 2 | 3 | import org.litepal.crud.LitePalSupport; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | import java.util.List; 8 | 9 | /** 10 | * @author LuQiChuang 11 | * @desc 12 | * @date 2021/6/9 18:13 13 | * @ver 1.0 14 | */ 15 | public abstract class Entity extends LitePalSupport implements Serializable { 16 | 17 | public abstract String getCurChapterTitle(); 18 | 19 | public abstract String getUpdateChapter(); 20 | 21 | public abstract String getImgUrl(); 22 | 23 | public abstract int getInfoId(); 24 | 25 | public abstract int getId(); 26 | 27 | public abstract void setId(int id); 28 | 29 | public abstract int getSourceId(); 30 | 31 | public abstract void setSourceId(int sourceId); 32 | 33 | public abstract String getTitle(); 34 | 35 | public abstract void setTitle(String title); 36 | 37 | public abstract int getStatus(); 38 | 39 | public abstract void setStatus(int status); 40 | 41 | public abstract String getAuthor(); 42 | 43 | public abstract void setAuthor(String author); 44 | 45 | public abstract EntityInfo getInfo(); 46 | 47 | public abstract void setInfo(EntityInfo entityInfo); 48 | 49 | public abstract List getInfoList(); 50 | 51 | public abstract void setInfoList(List infoList); 52 | 53 | public abstract int getPriority(); 54 | 55 | public abstract void setPriority(int priority); 56 | 57 | public abstract boolean isUpdate(); 58 | 59 | public abstract void setUpdate(boolean update); 60 | 61 | public abstract Date getDate(); 62 | 63 | public abstract void setDate(Date date); 64 | } 65 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/model/EntityInfo.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.model; 2 | 3 | import org.litepal.crud.LitePalSupport; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author LuQiChuang 11 | * @desc 12 | * @date 2021/6/9 19:22 13 | * @ver 1.0 14 | */ 15 | public abstract class EntityInfo extends LitePalSupport implements Serializable { 16 | 17 | public static final int DESC = 0; 18 | 19 | public static final int ASC = 1; 20 | 21 | public abstract String toStringDetail(); 22 | 23 | public abstract int getId(); 24 | 25 | public abstract void setId(int id); 26 | 27 | public abstract int getSourceId(); 28 | 29 | public abstract void setSourceId(int sourceId); 30 | 31 | public abstract String getTitle(); 32 | 33 | public abstract void setTitle(String title); 34 | 35 | public abstract String getAuthor(); 36 | 37 | public abstract void setAuthor(String author); 38 | 39 | public abstract String getDetailUrl(); 40 | 41 | public abstract void setDetailUrl(String detailUrl); 42 | 43 | public abstract String getImgUrl(); 44 | 45 | public abstract void setImgUrl(String imgUrl); 46 | 47 | public abstract String getLocalImgUrl(); 48 | 49 | public abstract void setLocalImgUrl(String localImgUrl); 50 | 51 | public abstract String getUpdateTime(); 52 | 53 | public abstract void setUpdateTime(String updateTime); 54 | 55 | public abstract String getUpdateChapter(); 56 | 57 | public abstract void setUpdateChapter(String updateChapter); 58 | 59 | public abstract String getUpdateStatus(); 60 | 61 | public abstract void setUpdateStatus(String updateStatus); 62 | 63 | public abstract String getCurChapterTitle(); 64 | 65 | public abstract void setCurChapterTitle(String curChapterTitle); 66 | 67 | public abstract String getIntro(); 68 | 69 | public abstract void setIntro(String intro); 70 | 71 | public abstract int getCurChapterId(); 72 | 73 | public abstract void setCurChapterId(int curChapterId); 74 | 75 | public abstract int getChapterNum(); 76 | 77 | public abstract void setChapterNum(int chapterNum); 78 | 79 | public abstract int getOrder(); 80 | 81 | public abstract void setOrder(int order); 82 | 83 | public abstract List getChapterInfoList(); 84 | 85 | public abstract void setChapterInfoList(List chapterInfoList); 86 | 87 | public abstract Map> getChapterInfoMap(); 88 | 89 | public abstract void setChapterInfoMap(Map> chapterInfoMap); 90 | } 91 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/model/Source.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.model; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import okhttp3.Request; 7 | import top.luqichuang.common.util.NetUtil; 8 | 9 | /** 10 | * @author LuQiChuang 11 | * @desc 12 | * @date 2021/6/10 14:54 13 | * @ver 1.0 14 | */ 15 | public interface Source { 16 | 17 | String SEARCH = "search"; 18 | String DETAIL = "detail"; 19 | String CONTENT = "content"; 20 | String RANK = "rank"; 21 | 22 | int getSourceId(); 23 | 24 | String getSourceName(); 25 | 26 | String getIndex(); 27 | 28 | default boolean isValid() { 29 | return true; 30 | } 31 | 32 | default String getCharsetName(String tag) { 33 | return "UTF-8"; 34 | } 35 | 36 | Request getSearchRequest(String searchString); 37 | 38 | default Request getDetailRequest(String detailUrl) { 39 | return NetUtil.getRequest(detailUrl); 40 | } 41 | 42 | default Request getContentRequest(String imageUrl) { 43 | return NetUtil.getRequest(imageUrl); 44 | } 45 | 46 | default Request getRankRequest(String rankUrl) { 47 | return NetUtil.getRequest(rankUrl); 48 | } 49 | 50 | default Request buildRequest(String html, String tag, Map data, Map map) { 51 | return null; 52 | } 53 | 54 | List getInfoList(String html); 55 | 56 | void setInfoDetail(T info, String html, Map map); 57 | 58 | List getContentList(String html, int chapterId, Map map); 59 | 60 | Map getRankMap(); 61 | 62 | List getRankInfoList(String html); 63 | 64 | Map getImageHeaders(); 65 | } 66 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/self/CommonCallback.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.self; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.io.IOException; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import okhttp3.Call; 10 | import okhttp3.Callback; 11 | import okhttp3.Request; 12 | import okhttp3.Response; 13 | import top.luqichuang.common.model.Source; 14 | import top.luqichuang.common.util.NetUtil; 15 | 16 | /** 17 | * @author LuQiChuang 18 | * @desc 19 | * @date 2021/6/10 14:52 20 | * @ver 1.0 21 | */ 22 | public abstract class CommonCallback implements Callback { 23 | 24 | private Request request; 25 | private Source source; 26 | private String tag; 27 | private Map map = new HashMap<>(); 28 | private Map data = new HashMap<>(); 29 | 30 | public CommonCallback(Request request, Source source, String tag) { 31 | this.request = request; 32 | this.source = source; 33 | this.tag = tag; 34 | } 35 | 36 | @Override 37 | public void onFailure(@NotNull Call call, @NotNull IOException e) { 38 | onFailure(e.getMessage()); 39 | } 40 | 41 | @Override 42 | public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { 43 | String html = null; 44 | Request req = null; 45 | initData(data); 46 | if (source != null) { 47 | html = getHtml(response, source.getCharsetName(tag)); 48 | req = source.buildRequest(html, tag, data, map); 49 | } 50 | // if (req != null && !request.toString().equals(req.toString())) { 51 | if (req != null) { 52 | request = req; 53 | NetUtil.startLoad(this); 54 | } else { 55 | onResponse(html, map); 56 | } 57 | } 58 | 59 | public static String getHtml(Response response, String charsetName) { 60 | String html; 61 | try { 62 | if (charsetName == null) { 63 | charsetName = "UTF-8"; 64 | } 65 | byte[] b = response.body().bytes(); 66 | html = new String(b, charsetName); 67 | } catch (Exception e) { 68 | html = ""; 69 | } 70 | return html; 71 | } 72 | 73 | protected void initData(Map data) { 74 | data.put("url", request.url().toString()); 75 | } 76 | 77 | public Request getRequest() { 78 | return request; 79 | } 80 | 81 | public abstract void onFailure(String errorMsg); 82 | 83 | public abstract void onResponse(String html, Map map); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/tst/BaseComicTest.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.tst; 2 | 3 | import top.luqichuang.mycomic.model.ComicInfo; 4 | 5 | /** 6 | * @author LuQiChuang 7 | * @desc 8 | * @date 2021/6/11 23:47 9 | * @ver 1.0 10 | */ 11 | public abstract class BaseComicTest extends BaseSourceTest { 12 | 13 | @Override 14 | protected ComicInfo getInfo() { 15 | return new ComicInfo(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/tst/BaseNovelTest.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.tst; 2 | 3 | import top.luqichuang.mynovel.model.NovelInfo; 4 | 5 | /** 6 | * @author LuQiChuang 7 | * @desc 8 | * @date 2021/6/11 23:48 9 | * @ver 1.0 10 | */ 11 | public abstract class BaseNovelTest extends BaseSourceTest { 12 | 13 | @Override 14 | protected NovelInfo getInfo() { 15 | return new NovelInfo(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/tst/BaseVideoTest.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.tst; 2 | 3 | import top.luqichuang.myvideo.model.VideoInfo; 4 | 5 | /** 6 | * @author LuQiChuang 7 | * @desc 8 | * @date 2021/6/15 14:40 9 | * @ver 1.0 10 | */ 11 | public abstract class BaseVideoTest extends BaseSourceTest { 12 | 13 | @Override 14 | protected VideoInfo getInfo() { 15 | return new VideoInfo(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.util; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.Locale; 6 | 7 | /** 8 | * @author LuQiChuang 9 | * @desc 日期工具 10 | * @date 2020/8/12 15:25 11 | * @ver 1.0 12 | */ 13 | public class DateUtil { 14 | 15 | private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); 16 | 17 | private static SimpleDateFormat backupFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); 18 | 19 | public static String format(Date date) { 20 | return date != null ? dateFormat.format(date) : null; 21 | } 22 | 23 | public static String formatAutoBackup(Date date) { 24 | return date != null ? backupFormat.format(date) : null; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.File; 6 | import java.io.FileReader; 7 | import java.io.FileWriter; 8 | import java.io.IOException; 9 | 10 | /** 11 | * @author LuQiChuang 12 | * @desc 13 | * @date 1/12/2021 11:05 AM 14 | * @ver 1.0 15 | */ 16 | public class FileUtil { 17 | 18 | public static final String MH_PATH = "D:\\Programming\\Files\\MH\\"; 19 | 20 | public static String readFile(String fileName) { 21 | try { 22 | String filePath = MH_PATH + fileName; 23 | File file = getFile(filePath); 24 | BufferedReader in = new BufferedReader(new FileReader(file)); 25 | String line; 26 | StringBuilder builder = new StringBuilder(); 27 | while ((line = in.readLine()) != null) { 28 | builder.append(line).append("\n"); 29 | } 30 | in.close(); 31 | return builder.toString(); 32 | } catch (IOException e) { 33 | e.printStackTrace(); 34 | } 35 | return ""; 36 | } 37 | 38 | public static void writeFile(String html, String fileName) { 39 | try { 40 | String filePath = MH_PATH + fileName; 41 | File file = getFile(filePath); 42 | BufferedWriter in = new BufferedWriter(new FileWriter(file)); 43 | in.write(html); 44 | in.close(); 45 | } catch (IOException e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | 50 | public static boolean exists(String filePath){ 51 | File file = new File(filePath); 52 | return file.exists(); 53 | } 54 | 55 | private static File getFile(String filePath) throws IOException { 56 | File file = new File(filePath); 57 | if (file.getParentFile() != null && !file.getParentFile().exists()) { 58 | file.getParentFile().mkdirs(); 59 | } 60 | if (!file.exists()) { 61 | file.createNewFile(); 62 | } 63 | return file; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/common/util/MapUtil.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Objects; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2021/1/13 0:02 12 | * @ver 1.0 13 | */ 14 | public class MapUtil { 15 | 16 | public static int indexOf(Map map, Object key) { 17 | int i = 0; 18 | for (Object o : map.keySet()) { 19 | if (Objects.equals(o, key)) { 20 | return i; 21 | } 22 | i++; 23 | } 24 | return -1; 25 | } 26 | 27 | public static K getKeyByValue(Map map, V value) { 28 | for (Map.Entry entry : map.entrySet()) { 29 | if (Objects.equals(entry.getValue(), value)) { 30 | return entry.getKey(); 31 | } 32 | } 33 | return null; 34 | } 35 | 36 | public static Map.Entry getFirst(Map map) { 37 | return map.entrySet().iterator().next(); 38 | } 39 | 40 | public static V getFirstValue(Map map) { 41 | if (map != null && !map.isEmpty()) { 42 | return map.values().iterator().next(); 43 | } 44 | return null; 45 | } 46 | 47 | public static List getKeyList(Map map) { 48 | return new ArrayList<>(map.keySet()); 49 | } 50 | 51 | public static V getValueByIndex(Map map, int index) { 52 | int i = 0; 53 | for (V value : map.values()) { 54 | if (i++ == index) { 55 | return value; 56 | } 57 | } 58 | return null; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/mycomic/model/BaseComicSource.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.mycomic.model; 2 | 3 | import java.util.Map; 4 | 5 | import top.luqichuang.common.en.SourceEnum; 6 | import top.luqichuang.common.model.Source; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2021/6/10 15:26 12 | * @ver 1.0 13 | */ 14 | public abstract class BaseComicSource implements Source { 15 | 16 | public abstract SourceEnum getSourceEnum(); 17 | 18 | @Override 19 | public final int getSourceId() { 20 | return getSourceEnum().ID; 21 | } 22 | 23 | @Override 24 | public final String getSourceName() { 25 | return getSourceEnum().NAME; 26 | } 27 | 28 | @Override 29 | public Map getImageHeaders() { 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/mynovel/model/BaseNovelSource.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.mynovel.model; 2 | 3 | import java.util.Map; 4 | 5 | import top.luqichuang.common.en.NSourceEnum; 6 | import top.luqichuang.common.model.Source; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2021/6/10 16:53 12 | * @ver 1.0 13 | */ 14 | public abstract class BaseNovelSource implements Source { 15 | 16 | public abstract NSourceEnum getNSourceEnum(); 17 | 18 | @Override 19 | public int getSourceId() { 20 | return getNSourceEnum().ID; 21 | } 22 | 23 | @Override 24 | public String getSourceName() { 25 | return getNSourceEnum().NAME; 26 | } 27 | 28 | @Override 29 | public Map getImageHeaders() { 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/top/luqichuang/myvideo/model/BaseVideoSource.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.myvideo.model; 2 | 3 | import java.util.Map; 4 | 5 | import top.luqichuang.common.en.VSourceEnum; 6 | import top.luqichuang.common.model.Source; 7 | 8 | /** 9 | * @author LuQiChuang 10 | * @desc 11 | * @date 2021/6/15 14:24 12 | * @ver 1.0 13 | */ 14 | public abstract class BaseVideoSource implements Source { 15 | 16 | public abstract VSourceEnum getVSourceEnum(); 17 | 18 | @Override 19 | public final int getSourceId() { 20 | return getVSourceEnum().ID; 21 | } 22 | 23 | @Override 24 | public final String getSourceName() { 25 | return getVSourceEnum().NAME; 26 | } 27 | 28 | @Override 29 | public Map getImageHeaders() { 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/test/java/top/luqichuang/common/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package top.luqichuang.common; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC184722/MyComic/94edf2b461beb63a789a757b8f79c2c060c08e66/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Nov 15 17:07:41 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':common' 2 | include ':app' 3 | rootProject.name = "MyComic" --------------------------------------------------------------------------------