├── app ├── .gitignore ├── src │ ├── main │ │ ├── java │ │ │ └── io │ │ │ │ └── legado │ │ │ │ └── app │ │ │ │ ├── base │ │ │ │ ├── README.md │ │ │ │ ├── VMBaseFragment.kt │ │ │ │ ├── adapter │ │ │ │ │ ├── animations │ │ │ │ │ │ ├── BaseAnimation.kt │ │ │ │ │ │ ├── SlideInBottomAnimation.kt │ │ │ │ │ │ ├── SlideInLeftAnimation.kt │ │ │ │ │ │ ├── SlideInRightAnimation.kt │ │ │ │ │ │ └── AlphaInAnimation.kt │ │ │ │ │ └── ItemViewHolder.kt │ │ │ │ └── VMBaseActivity.kt │ │ │ │ ├── help │ │ │ │ ├── README.md │ │ │ │ ├── http │ │ │ │ │ ├── RequestMethod.kt │ │ │ │ │ ├── OkhttpUncaughtExceptionHandler.kt │ │ │ │ │ └── OkHttpExceptionInterceptor.kt │ │ │ │ ├── glide │ │ │ │ │ ├── progress │ │ │ │ │ │ └── OnProgressListener.kt │ │ │ │ │ └── GlideHeaders.kt │ │ │ │ ├── ExecutorService.kt │ │ │ │ ├── storage │ │ │ │ │ └── BackupAES.kt │ │ │ │ ├── coroutine │ │ │ │ │ ├── ActivelyCancelException.kt │ │ │ │ │ └── CoroutineContainer.kt │ │ │ │ ├── book │ │ │ │ │ └── BookContent.kt │ │ │ │ ├── PaintPool.kt │ │ │ │ └── update │ │ │ │ │ └── AppUpdate.kt │ │ │ │ ├── web │ │ │ │ └── ReadMe.md │ │ │ │ ├── lib │ │ │ │ ├── README.md │ │ │ │ ├── aliyun │ │ │ │ │ └── ALiYun.kt │ │ │ │ ├── mobi │ │ │ │ │ ├── entities │ │ │ │ │ │ ├── KF8Pos.kt │ │ │ │ │ │ ├── IndexTag.kt │ │ │ │ │ │ ├── FdstHeader.kt │ │ │ │ │ │ ├── KF8Resource.kt │ │ │ │ │ │ ├── TOC.kt │ │ │ │ │ │ ├── TagxHeader.kt │ │ │ │ │ │ ├── Ptagx.kt │ │ │ │ │ │ ├── TagxTag.kt │ │ │ │ │ │ ├── ExthRecordType.kt │ │ │ │ │ │ ├── IndexData.kt │ │ │ │ │ │ ├── KF8Header.kt │ │ │ │ │ │ ├── PalmDocHeader.kt │ │ │ │ │ │ ├── Skeleton.kt │ │ │ │ │ │ ├── Fragment.kt │ │ │ │ │ │ ├── MobiEntryHeaders.kt │ │ │ │ │ │ ├── IndexEntry.kt │ │ │ │ │ │ ├── KF6Section.kt │ │ │ │ │ │ ├── NCX.kt │ │ │ │ │ │ ├── MobiMetadata.kt │ │ │ │ │ │ ├── KF8Section.kt │ │ │ │ │ │ ├── IndxHeader.kt │ │ │ │ │ │ └── MobiHeader.kt │ │ │ │ │ ├── decompress │ │ │ │ │ │ ├── CDICData.kt │ │ │ │ │ │ ├── Decompressor.kt │ │ │ │ │ │ └── PlainDecompressor.kt │ │ │ │ │ └── utils │ │ │ │ │ │ └── BitwiseExtensions.kt │ │ │ │ ├── permission │ │ │ │ │ ├── OnErrorCallback.kt │ │ │ │ │ ├── OnPermissionsGrantedCallback.kt │ │ │ │ │ ├── OnPermissionsDeniedCallback.kt │ │ │ │ │ ├── OnPermissionsResultCallback.kt │ │ │ │ │ ├── OnRequestPermissionsResultCallback.kt │ │ │ │ │ └── RequestPlugins.kt │ │ │ │ ├── cronet │ │ │ │ │ ├── CallbackStep.kt │ │ │ │ │ └── CallbackResult.kt │ │ │ │ ├── dialogs │ │ │ │ │ └── SelectItem.kt │ │ │ │ ├── webdav │ │ │ │ │ └── WebDavException.kt │ │ │ │ └── theme │ │ │ │ │ └── view │ │ │ │ │ ├── ThemeProgressBar.kt │ │ │ │ │ ├── ThemeCheckBox.kt │ │ │ │ │ ├── ThemeRadioButton.kt │ │ │ │ │ ├── ThemeSeekBar.kt │ │ │ │ │ └── ThemeSwitch.kt │ │ │ │ ├── model │ │ │ │ ├── README.md │ │ │ │ ├── localBook │ │ │ │ │ ├── README.md │ │ │ │ │ └── BaseLocalBookParse.kt │ │ │ │ └── Download.kt │ │ │ │ ├── constant │ │ │ │ ├── Theme.kt │ │ │ │ ├── Status.kt │ │ │ │ ├── SourceType.kt │ │ │ │ ├── NotificationId.kt │ │ │ │ ├── BookSourceType.kt │ │ │ │ └── PageAnim.kt │ │ │ │ ├── exception │ │ │ │ ├── RegexTimeoutException.kt │ │ │ │ ├── InvalidBooksDirException.kt │ │ │ │ ├── EmptyFileException.kt │ │ │ │ ├── TocEmptyException.kt │ │ │ │ ├── ContentEmptyException.kt │ │ │ │ ├── ConcurrentException.kt │ │ │ │ ├── NoBooksDirException.kt │ │ │ │ └── NoStackTraceException.kt │ │ │ │ ├── ui │ │ │ │ ├── book │ │ │ │ │ ├── import │ │ │ │ │ │ ├── remote │ │ │ │ │ │ │ ├── RemoteBookSort.kt │ │ │ │ │ │ │ └── ServersViewModel.kt │ │ │ │ │ │ └── local │ │ │ │ │ │ │ └── ImportBook.kt │ │ │ │ │ ├── read │ │ │ │ │ │ └── page │ │ │ │ │ │ │ ├── entities │ │ │ │ │ │ │ ├── PageDirection.kt │ │ │ │ │ │ │ └── column │ │ │ │ │ │ │ │ └── BaseColumn.kt │ │ │ │ │ │ │ └── provider │ │ │ │ │ │ │ └── LayoutProgressListener.kt │ │ │ │ │ ├── manga │ │ │ │ │ │ ├── entities │ │ │ │ │ │ │ ├── BaseMangaPage.kt │ │ │ │ │ │ │ ├── MangaContent.kt │ │ │ │ │ │ │ ├── MangaChapter.kt │ │ │ │ │ │ │ ├── ReaderLoading.kt │ │ │ │ │ │ │ └── MangaPage.kt │ │ │ │ │ │ ├── config │ │ │ │ │ │ │ └── MangaColorFilterConfig.kt │ │ │ │ │ │ └── recyclerview │ │ │ │ │ │ │ └── MangaLayoutManager.kt │ │ │ │ │ └── source │ │ │ │ │ │ └── manage │ │ │ │ │ │ └── BookSourceSort.kt │ │ │ │ ├── main │ │ │ │ │ ├── MainFragmentInterface.kt │ │ │ │ │ └── explore │ │ │ │ │ │ └── ExploreDiffItemCallBack.kt │ │ │ │ ├── qrcode │ │ │ │ │ └── ScanResultCallback.kt │ │ │ │ ├── rss │ │ │ │ │ ├── favorites │ │ │ │ │ │ └── RssFavoritesViewModel.kt │ │ │ │ │ ├── read │ │ │ │ │ │ └── VisibleWebView.kt │ │ │ │ │ └── article │ │ │ │ │ │ └── BaseRssArticlesAdapter.kt │ │ │ │ ├── widget │ │ │ │ │ ├── anima │ │ │ │ │ │ └── explosion_field │ │ │ │ │ │ │ └── OnAnimatorListener.kt │ │ │ │ │ ├── recycler │ │ │ │ │ │ ├── scroller │ │ │ │ │ │ │ └── FastScrollStateChangeListener.kt │ │ │ │ │ │ └── VerticalDivider.kt │ │ │ │ │ ├── seekbar │ │ │ │ │ │ └── SeekBarChangeListener.kt │ │ │ │ │ ├── text │ │ │ │ │ │ ├── PrimaryTextView.kt │ │ │ │ │ │ └── SecondaryTextView.kt │ │ │ │ │ └── image │ │ │ │ │ │ └── ImageButton.kt │ │ │ │ ├── config │ │ │ │ │ └── ConfigTag.kt │ │ │ │ └── README.md │ │ │ │ ├── utils │ │ │ │ ├── objectpool │ │ │ │ │ ├── ObjectPoolExtensions.kt │ │ │ │ │ ├── ObjectPool.kt │ │ │ │ │ ├── BaseSafeObjectPool.kt │ │ │ │ │ ├── ObjectPoolLocked.kt │ │ │ │ │ └── BaseObjectPool.kt │ │ │ │ ├── BookChapterExtensions.kt │ │ │ │ ├── canvasrecorder │ │ │ │ │ ├── pools │ │ │ │ │ │ ├── PicturePool.kt │ │ │ │ │ │ ├── CanvasPool.kt │ │ │ │ │ │ └── RenderNodePool.kt │ │ │ │ │ └── CanvasRecorder.kt │ │ │ │ ├── WindowInsetsExtensions.kt │ │ │ │ ├── MenuItemExtensions.kt │ │ │ │ ├── MutableLiveDataExtensions.kt │ │ │ │ ├── ConfigurationExtensions.kt │ │ │ │ ├── Throttle.kt │ │ │ │ ├── AsyncFileHandler.kt │ │ │ │ ├── AnimationExtensions.kt │ │ │ │ ├── ThrowableExtensions.kt │ │ │ │ └── IntentExtensions.kt │ │ │ │ ├── data │ │ │ │ ├── entities │ │ │ │ │ ├── ReadRecordShow.kt │ │ │ │ │ ├── Cookie.kt │ │ │ │ │ ├── RssReadRecord.kt │ │ │ │ │ ├── rule │ │ │ │ │ │ ├── ExploreKind.kt │ │ │ │ │ │ ├── BookListRule.kt │ │ │ │ │ │ └── RowUi.kt │ │ │ │ │ ├── Cache.kt │ │ │ │ │ ├── BookChapterReview.kt │ │ │ │ │ ├── ReadRecord.kt │ │ │ │ │ ├── RuleSub.kt │ │ │ │ │ └── SearchKeyword.kt │ │ │ │ ├── README.md │ │ │ │ └── dao │ │ │ │ │ └── RssReadRecordDao.kt │ │ │ │ ├── service │ │ │ │ └── README.md │ │ │ │ └── README.md │ │ ├── res │ │ │ ├── anim │ │ │ │ ├── anim_none.xml │ │ │ │ ├── anim_readbook_bottom_in.xml │ │ │ │ ├── anim_readbook_bottom_out.xml │ │ │ │ ├── anim_readbook_top_in.xml │ │ │ │ └── anim_readbook_top_out.xml │ │ │ ├── drawable │ │ │ │ ├── image_rss.jpg │ │ │ │ ├── icon_read_book.png │ │ │ │ ├── image_legado.png │ │ │ │ ├── image_cover_default.jpg │ │ │ │ ├── image_loading_error.png │ │ │ │ ├── image_rss_article.jpg │ │ │ │ ├── shape_space_divider.xml │ │ │ │ ├── bg_item_focused_on_tv.xml │ │ │ │ ├── selector_circle_btn_bg.xml │ │ │ │ ├── bg_edit.xml │ │ │ │ ├── ic_divider.xml │ │ │ │ ├── shape_fillet_btn.xml │ │ │ │ ├── shape_pop_checkaddshelf_bg.xml │ │ │ │ ├── shape_card_view.xml │ │ │ │ ├── shape_translucent_card.xml │ │ │ │ ├── bg_find_book_group.xml │ │ │ │ ├── shape_fillet_btn_press.xml │ │ │ │ ├── bg_popup_menu.xml │ │ │ │ ├── bg_gradient.xml │ │ │ │ ├── bg_shadow_top.xml │ │ │ │ ├── shape_text_cursor.xml │ │ │ │ ├── bg_shadow_bottom.xml │ │ │ │ ├── bg_shadow_bottom_night.xml │ │ │ │ ├── bg_shadow_top_night.xml │ │ │ │ ├── bg_prefs_color.xml │ │ │ │ ├── selector_btn_accent_bg.xml │ │ │ │ ├── recyclerview_divider_horizontal.xml │ │ │ │ ├── shape_circle.xml │ │ │ │ ├── shape_radius_1dp.xml │ │ │ │ ├── bg_eink_border_dialog.xml │ │ │ │ ├── shape_radius_10dp.xml │ │ │ │ ├── ic_bottom_books.xml │ │ │ │ ├── ic_bottom_person.xml │ │ │ │ ├── ic_bottom_explore.xml │ │ │ │ ├── ic_bottom_rss_feed.xml │ │ │ │ ├── selector_fillet_btn_bg.xml │ │ │ │ ├── ic_play_24dp.xml │ │ │ │ ├── ic_reduce.xml │ │ │ │ ├── ic_arrow_drop_up.xml │ │ │ │ ├── ic_launcher4_b.xml │ │ │ │ ├── ic_launcher7_b.xml │ │ │ │ ├── ic_stop_black_24dp.xml │ │ │ │ ├── ic_arrow_drop_down.xml │ │ │ │ ├── ic_launcher5_b.xml │ │ │ │ ├── bg_chapter_item_divider.xml │ │ │ │ ├── ic_pause_24dp.xml │ │ │ │ ├── ic_skip_next.xml │ │ │ │ ├── ic_skip_previous.xml │ │ │ │ ├── ic_baseline_sort_24.xml │ │ │ │ ├── ic_download.xml │ │ │ │ ├── ic_fast_forward.xml │ │ │ │ ├── selector_common_bg.xml │ │ │ │ ├── ic_check.xml │ │ │ │ ├── ic_expand_less.xml │ │ │ │ ├── ic_expand_more.xml │ │ │ │ ├── ic_fast_rewind.xml │ │ │ │ ├── ic_menu.xml │ │ │ │ ├── ic_arrow_back.xml │ │ │ │ ├── ic_arrow_down.xml │ │ │ │ ├── bg_searchview.xml │ │ │ │ ├── ic_arrow_right.xml │ │ │ │ ├── ic_star.xml │ │ │ │ ├── ic_cursor_left.xml │ │ │ │ ├── ic_toc.xml │ │ │ │ ├── ic_cursor_right.xml │ │ │ │ ├── ic_swap_horiz.xml │ │ │ │ ├── ic_bottom_explore_s.xml │ │ │ │ ├── recyclerview_divider_vertical.xml │ │ │ │ ├── ic_folder.xml │ │ │ │ ├── ic_folder_open.xml │ │ │ │ ├── selector_tv_black.xml │ │ │ │ ├── ic_storage_black_24dp.xml │ │ │ │ ├── ic_bookmark.xml │ │ │ │ ├── bg_img_border.xml │ │ │ │ ├── ic_baseline_close.xml │ │ │ │ ├── ic_folder_outline.xml │ │ │ │ ├── ic_lock_outline.xml │ │ │ │ ├── ic_backup.xml │ │ │ │ ├── ic_exit.xml │ │ │ │ ├── ic_more_vert.xml │ │ │ │ ├── ic_add.xml │ │ │ │ ├── ic_pause_outline_24dp.xml │ │ │ │ ├── ic_star_border.xml │ │ │ │ ├── bg_eink_border_top.xml │ │ │ │ ├── ic_bottom_person_s.xml │ │ │ │ ├── ic_volume_up.xml │ │ │ │ ├── bg_eink_border_bottom.xml │ │ │ │ ├── ic_refresh_white_24dp.xml │ │ │ │ ├── ic_create_folder_outline.xml │ │ │ │ ├── ic_outline_delete.xml │ │ │ │ ├── ic_restore.xml │ │ │ │ ├── ic_scoring.xml │ │ │ │ ├── ic_sort.xml │ │ │ │ ├── ic_cfg_backup.xml │ │ │ │ └── ic_bottom_person_e.xml │ │ │ ├── raw │ │ │ │ └── silent_sound.mp3 │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── layout │ │ │ │ ├── view_icon.xml │ │ │ │ ├── item_log.xml │ │ │ │ ├── activity_source_login.xml │ │ │ │ ├── view_action_button.xml │ │ │ │ ├── view_title_bar.xml │ │ │ │ ├── dialog_number_picker.xml │ │ │ │ ├── view_title_bar_dark.xml │ │ │ │ ├── view_tab_layout.xml │ │ │ │ ├── item_radio_button.xml │ │ │ │ ├── popup_keyboard_tool.xml │ │ │ │ ├── dialog_photo_view.xml │ │ │ │ ├── item_read_style.xml │ │ │ │ ├── view_tab_layout_min.xml │ │ │ │ └── fragment_rss_articles.xml │ │ │ ├── menu │ │ │ │ ├── file_long_click.xml │ │ │ │ ├── source_sub_item.xml │ │ │ │ ├── import_book_sel.xml │ │ │ │ ├── source_picker.xml │ │ │ │ ├── dialog_text.xml │ │ │ │ ├── theme_list.xml │ │ │ │ ├── app_update.xml │ │ │ │ ├── theme_config.xml │ │ │ │ ├── bookmark.xml │ │ │ │ ├── qr_code_scan.xml │ │ │ │ ├── group_manage.xml │ │ │ │ ├── servers.xml │ │ │ │ ├── keyboard_assists_config.xml │ │ │ │ ├── server_config.xml │ │ │ │ ├── source_subscription.xml │ │ │ │ ├── book_info_edit.xml │ │ │ │ ├── file_chooser.xml │ │ │ │ ├── search_view.xml │ │ │ │ ├── app_log.xml │ │ │ │ ├── crash_log.xml │ │ │ │ ├── main_explore.xml │ │ │ │ ├── rss_read_record.xml │ │ │ │ ├── import_replace.xml │ │ │ │ ├── replace_rule_item.xml │ │ │ │ ├── rss_source_item.xml │ │ │ │ ├── txt_toc_rule_item.xml │ │ │ │ ├── save.xml │ │ │ │ ├── code_edit.xml │ │ │ │ ├── content_search.xml │ │ │ │ ├── main_my.xml │ │ │ │ ├── source_webview_login.xml │ │ │ │ ├── book_group_manage.xml │ │ │ │ ├── font_select.xml │ │ │ │ ├── change_cover.xml │ │ │ │ ├── rss_main_item.xml │ │ │ │ ├── book_search_scope.xml │ │ │ │ ├── rss_source_debug.xml │ │ │ │ ├── open_url_confirm.xml │ │ │ │ ├── backup_restore.xml │ │ │ │ └── txt_toc_rule_edit.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── launcher3.xml │ │ │ │ ├── launcher5.xml │ │ │ │ ├── launcher1.xml │ │ │ │ ├── launcher2.xml │ │ │ │ ├── launcher4.xml │ │ │ │ ├── launcher6.xml │ │ │ │ └── ic_launcher.xml │ │ │ ├── color │ │ │ │ └── selector_image.xml │ │ │ ├── values │ │ │ │ └── ids.xml │ │ │ └── xml │ │ │ │ └── network_security_config.xml │ │ ├── assets │ │ │ ├── bg │ │ │ │ ├── 午后沙滩.jpg │ │ │ │ ├── 宁静夜色.jpg │ │ │ │ ├── 山水墨影.jpg │ │ │ │ ├── 山水画.jpg │ │ │ │ ├── 护眼漫绿.jpg │ │ │ │ ├── 新羊皮纸.jpg │ │ │ │ ├── 明媚倾城.jpg │ │ │ │ ├── 深宫魅影.jpg │ │ │ │ ├── 清新时光.jpg │ │ │ │ ├── 羊皮纸1.jpg │ │ │ │ ├── 羊皮纸2.jpg │ │ │ │ ├── 羊皮纸3.jpg │ │ │ │ ├── 羊皮纸4.jpg │ │ │ │ └── 边彩画布.jpg │ │ │ ├── epub │ │ │ │ ├── logo.png │ │ │ │ ├── chapter.html │ │ │ │ └── intro.html │ │ │ ├── defaultData │ │ │ │ └── coverRule.json │ │ │ ├── font │ │ │ │ └── number.ttf │ │ │ ├── web │ │ │ │ ├── favicon.ico │ │ │ │ ├── images │ │ │ │ │ └── bg.jpg │ │ │ │ ├── vue │ │ │ │ │ ├── favicon.ico │ │ │ │ │ └── assets │ │ │ │ │ │ ├── popfont-WaOB0hHG.ttf │ │ │ │ │ │ ├── iconfont-PstzbNMW.woff │ │ │ │ │ │ ├── loading-DkQYEuap.css │ │ │ │ │ │ ├── shelffont-D-W4UqG-.ttf │ │ │ │ │ │ └── loading-6mEK85yy.js │ │ │ │ ├── help │ │ │ │ │ ├── md │ │ │ │ │ │ ├── replaceRuleHelp.md │ │ │ │ │ │ ├── dictRuleHelp.md │ │ │ │ │ │ ├── SourceMRssHelp.md │ │ │ │ │ │ ├── httpTTSHelp.md │ │ │ │ │ │ ├── debugHelp.md │ │ │ │ │ │ ├── webDavHelp.md │ │ │ │ │ │ └── SourceMBookHelp.md │ │ │ │ │ └── index.html │ │ │ │ └── uploadBook │ │ │ │ │ └── img │ │ │ │ │ ├── close.png │ │ │ │ │ ├── logo.png │ │ │ │ │ ├── right.png │ │ │ │ │ ├── safari.png │ │ │ │ │ ├── wrong.png │ │ │ │ │ ├── notice01.png │ │ │ │ │ └── notice02.png │ │ │ ├── storageHelp.md │ │ │ ├── privacyPolicy.md │ │ │ └── cronet.json │ │ └── ic_launcher-web.png │ ├── debug │ │ └── res │ │ │ ├── values-zh │ │ │ └── strings.xml │ │ │ └── values │ │ │ └── strings.xml │ └── test │ │ └── java │ │ └── io │ │ └── legado │ │ └── app │ │ └── ExampleUnitTest.kt └── cronetlib │ ├── cronet_api.jar │ ├── cronet_shared_java.jar │ ├── cronet_impl_common_java.jar │ ├── cronet_impl_native_java.jar │ └── cronet_impl_platform_java.jar ├── modules ├── book │ ├── .gitignore │ ├── consumer-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── me │ │ └── ag2s │ │ ├── epublib │ │ ├── domain │ │ │ ├── ManifestProperties.java │ │ │ ├── LazyResourceProvider.java │ │ │ ├── ManifestItemRefProperties.java │ │ │ └── ManifestItemProperties.java │ │ ├── browsersupport │ │ │ ├── package-info.java │ │ │ └── NavigationEventListener.java │ │ ├── epub │ │ │ ├── HtmlProcessor.java │ │ │ └── BookProcessor.java │ │ └── Constants.java │ │ ├── base │ │ └── ThrowableUtils.java │ │ └── umdlib │ │ └── domain │ │ └── UmdEnd.java ├── web │ ├── .browserslistrc │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── imgs │ │ │ │ ├── github.png │ │ │ │ └── themes │ │ │ │ │ ├── body_0.png │ │ │ │ │ ├── body_1.png │ │ │ │ │ ├── body_2.png │ │ │ │ │ ├── body_3.png │ │ │ │ │ ├── body_5.png │ │ │ │ │ ├── body_6.png │ │ │ │ │ ├── popup_0.png │ │ │ │ │ ├── popup_1.png │ │ │ │ │ ├── popup_2.png │ │ │ │ │ ├── popup_3.png │ │ │ │ │ ├── popup_5.png │ │ │ │ │ ├── popup_6.png │ │ │ │ │ ├── content_0.png │ │ │ │ │ ├── content_1.png │ │ │ │ │ ├── content_2.png │ │ │ │ │ ├── content_3.png │ │ │ │ │ ├── content_5.png │ │ │ │ │ └── content_6.png │ │ │ ├── fonts │ │ │ │ ├── popfont.ttf │ │ │ │ ├── iconfont.woff │ │ │ │ ├── shelffont.ttf │ │ │ │ ├── iconfont.css │ │ │ │ ├── popfont.css │ │ │ │ └── shelffont.css │ │ │ ├── sourceeditor.css │ │ │ ├── code.css │ │ │ ├── bookshelf.css │ │ │ └── kbd.css │ │ ├── hooks │ │ │ └── loading.css │ │ ├── store │ │ │ └── index.ts │ │ ├── pages │ │ │ ├── source │ │ │ │ ├── main.js │ │ │ │ ├── index.html │ │ │ │ └── README.md │ │ │ └── bookshelf │ │ │ │ ├── index.html │ │ │ │ ├── README.md │ │ │ │ └── main.js │ │ ├── web.d.ts │ │ ├── api │ │ │ └── axios.ts │ │ ├── router │ │ │ ├── index.ts │ │ │ ├── bookRouter.ts │ │ │ └── sourceRouter.ts │ │ ├── plugins │ │ │ └── jump.d.ts │ │ └── main.ts │ ├── public │ │ └── favicon.ico │ ├── env.d.ts │ ├── .prettierignore │ ├── .prettierrc.json │ ├── .editorconfig │ ├── tsconfig.json │ ├── index.html │ ├── .gitignore │ ├── tsconfig.app.json │ ├── tsconfig.node.json │ └── eslint.config.mjs └── rhino │ ├── lib │ └── rhino-1.7.14.jar │ └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── script │ ├── RhinoContextFactory.kt │ ├── rhino │ ├── RhinoErrors.kt │ ├── JavaObjectWrapFactory.kt │ ├── VMBridgeReflect.kt │ └── CollectionExtensions.kt │ ├── Compilable.kt │ ├── ScriptBindingsExtensions.kt │ ├── Bindings.kt │ └── Invocable.kt ├── avd.sh ├── avd.bat ├── .github ├── workflows │ └── legado.jks └── ISSUE_TEMPLATE │ └── config.yml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore └── CHANGELOG.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /so -------------------------------------------------------------------------------- /modules/book/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /modules/book/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avd.sh: -------------------------------------------------------------------------------- 1 | emulator -avd $1 -no-snapshot-load -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/README.md: -------------------------------------------------------------------------------- 1 | # 基类 -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/README.md: -------------------------------------------------------------------------------- 1 | # 放置一些帮助类 -------------------------------------------------------------------------------- /avd.bat: -------------------------------------------------------------------------------- 1 | emulator -avd %1 -dns-server 8.8.8.8 -no-snapshot-load -------------------------------------------------------------------------------- /modules/web/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /modules/web/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_none.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.github/workflows/legado.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/.github/workflows/legado.jks -------------------------------------------------------------------------------- /app/cronetlib/cronet_api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/cronetlib/cronet_api.jar -------------------------------------------------------------------------------- /app/src/main/assets/bg/午后沙滩.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/午后沙滩.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/宁静夜色.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/宁静夜色.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/山水墨影.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/山水墨影.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/山水画.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/山水画.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/护眼漫绿.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/护眼漫绿.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/新羊皮纸.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/新羊皮纸.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/明媚倾城.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/明媚倾城.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/深宫魅影.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/深宫魅影.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/清新时光.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/清新时光.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/羊皮纸1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/羊皮纸1.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/羊皮纸2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/羊皮纸2.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/羊皮纸3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/羊皮纸3.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/羊皮纸4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/羊皮纸4.jpg -------------------------------------------------------------------------------- /app/src/main/assets/bg/边彩画布.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/bg/边彩画布.jpg -------------------------------------------------------------------------------- /modules/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/public/favicon.ico -------------------------------------------------------------------------------- /app/src/main/assets/epub/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/epub/logo.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /modules/book/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /modules/rhino/lib/rhino-1.7.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/rhino/lib/rhino-1.7.14.jar -------------------------------------------------------------------------------- /modules/rhino/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /modules/web/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "vue3-virtual-scroll-list"; 4 | -------------------------------------------------------------------------------- /app/cronetlib/cronet_shared_java.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/cronetlib/cronet_shared_java.jar -------------------------------------------------------------------------------- /app/src/main/assets/defaultData/coverRule.json: -------------------------------------------------------------------------------- 1 | { 2 | "enable": false, 3 | "searchUrl": "", 4 | "coverRule": "" 5 | } -------------------------------------------------------------------------------- /app/src/main/assets/font/number.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/font/number.ttf -------------------------------------------------------------------------------- /app/src/main/assets/web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/favicon.ico -------------------------------------------------------------------------------- /app/src/main/assets/web/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/images/bg.jpg -------------------------------------------------------------------------------- /app/src/main/assets/web/vue/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/vue/favicon.ico -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_rss.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/drawable/image_rss.jpg -------------------------------------------------------------------------------- /app/src/main/res/raw/silent_sound.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/raw/silent_sound.mp3 -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/github.png -------------------------------------------------------------------------------- /app/cronetlib/cronet_impl_common_java.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/cronetlib/cronet_impl_common_java.jar -------------------------------------------------------------------------------- /app/cronetlib/cronet_impl_native_java.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/cronetlib/cronet_impl_native_java.jar -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/web/ReadMe.md: -------------------------------------------------------------------------------- 1 | # web服务 2 | 3 | * controller 数据操作 4 | * HttpServer http服务 5 | * WebSocketServer 持续通讯服务 -------------------------------------------------------------------------------- /modules/web/.prettierignore: -------------------------------------------------------------------------------- 1 | # d.ts files Generated by unplugin-auto unplugin-vue-components 2 | auto-imports.d.ts 3 | components.d.ts -------------------------------------------------------------------------------- /modules/web/src/assets/fonts/popfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/fonts/popfont.ttf -------------------------------------------------------------------------------- /app/cronetlib/cronet_impl_platform_java.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/cronetlib/cronet_impl_platform_java.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_read_book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/drawable/icon_read_book.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_legado.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/drawable/image_legado.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /modules/web/src/assets/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/fonts/iconfont.woff -------------------------------------------------------------------------------- /modules/web/src/assets/fonts/shelffont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/fonts/shelffont.ttf -------------------------------------------------------------------------------- /app/src/main/assets/web/help/md/replaceRuleHelp.md: -------------------------------------------------------------------------------- 1 | # 替换管理界面帮助 2 | 3 | * 替换规则是用来替换正文内容的一种规则 4 | * 菜单可以新建和导入规则 5 | * 可以拖动排序 6 | * 可以选择操作 -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/body_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/body_0.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/body_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/body_1.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/body_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/body_2.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/body_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/body_3.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/body_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/body_5.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/body_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/body_6.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/popup_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/popup_0.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/popup_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/popup_1.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/popup_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/popup_2.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/popup_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/popup_3.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/popup_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/popup_5.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/popup_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/popup_6.png -------------------------------------------------------------------------------- /app/src/main/assets/storageHelp.md: -------------------------------------------------------------------------------- 1 | * 由于安卓的存储访问限制,阅读需要设置**公共目录下的子目录**来实现书籍拷贝、下载,例如Documents/Books、Download/Books 2 | * 如不设置,将无法正常使用本地书籍、webDav书籍的相关功能 -------------------------------------------------------------------------------- /app/src/main/assets/web/uploadBook/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/uploadBook/img/close.png -------------------------------------------------------------------------------- /app/src/main/assets/web/uploadBook/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/uploadBook/img/logo.png -------------------------------------------------------------------------------- /app/src/main/assets/web/uploadBook/img/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/uploadBook/img/right.png -------------------------------------------------------------------------------- /app/src/main/assets/web/uploadBook/img/safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/uploadBook/img/safari.png -------------------------------------------------------------------------------- /app/src/main/assets/web/uploadBook/img/wrong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/uploadBook/img/wrong.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_cover_default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/drawable/image_cover_default.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_loading_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/drawable/image_loading_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_rss_article.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/drawable/image_rss_article.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/content_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/content_0.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/content_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/content_1.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/content_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/content_2.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/content_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/content_3.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/content_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/content_5.png -------------------------------------------------------------------------------- /modules/web/src/assets/imgs/themes/content_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/modules/web/src/assets/imgs/themes/content_6.png -------------------------------------------------------------------------------- /app/src/main/assets/web/uploadBook/img/notice01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/uploadBook/img/notice01.png -------------------------------------------------------------------------------- /app/src/main/assets/web/uploadBook/img/notice02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/uploadBook/img/notice02.png -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/http/RequestMethod.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.http 2 | 3 | enum class RequestMethod { 4 | GET, POST 5 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/README.md: -------------------------------------------------------------------------------- 1 | # 放置一些copy过来的库 2 | 3 | * dialogs 弹出框 4 | * icu4j 编码识别库 5 | * permission 权限申请库 6 | * theme 主题 7 | * webDav 网络存储 -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/model/README.md: -------------------------------------------------------------------------------- 1 | # 放置一些模块类 2 | 3 | * analyzeRule 书源规则解析 4 | * localBook 本地书籍解析 5 | * rss 订阅规则解析 6 | * webBook 获取网络书籍 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/assets/web/vue/assets/popfont-WaOB0hHG.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/vue/assets/popfont-WaOB0hHG.ttf -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/constant/Theme.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.constant 2 | 3 | enum class Theme { 4 | Dark, Light, Auto, Transparent, EInk; 5 | } -------------------------------------------------------------------------------- /app/src/main/assets/web/vue/assets/iconfont-PstzbNMW.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/vue/assets/iconfont-PstzbNMW.woff -------------------------------------------------------------------------------- /app/src/main/assets/web/vue/assets/loading-DkQYEuap.css: -------------------------------------------------------------------------------- 1 | .el-loading-spinner{font-size:36px;color:#b5b5b5}.el-loading-text{font-weight:500;color:#b5b5b5!important} 2 | -------------------------------------------------------------------------------- /app/src/main/assets/web/vue/assets/shelffont-D-W4UqG-.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgz0227/legado/HEAD/app/src/main/assets/web/vue/assets/shelffont-D-W4UqG-.ttf -------------------------------------------------------------------------------- /modules/web/src/assets/fonts/iconfont.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | @font-face { 3 | font-family: 'iconfont'; 4 | src: url('./iconfont.woff') format('woff'); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/debug/res/values-zh/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 阅读·D 3 | 阅读·D·搜索 4 | -------------------------------------------------------------------------------- /app/src/main/assets/web/help/md/dictRuleHelp.md: -------------------------------------------------------------------------------- 1 | ## 字典规则说明 2 | 3 | * 字典规则是用在正文文字选择菜单字典里的规则,通常用来做翻译或者查找 4 | * urlRule 5 | * 同书源的url规则 6 | * showRule 7 | * 用来提取显示到对话框里面内容的规则 -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/RegexTimeoutException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.exception 2 | 3 | class RegexTimeoutException(msg: String) : NoStackTraceException(msg) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/aliyun/ALiYun.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.aliyun 2 | 3 | object ALiYun { 4 | 5 | fun getToken() { 6 | 7 | } 8 | 9 | 10 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/KF8Pos.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class KF8Pos( 4 | val fid: Int, 5 | val offset: Int 6 | ) 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/import/remote/RemoteBookSort.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.import.remote 2 | 3 | enum class RemoteBookSort { 4 | Default, Name 5 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/main/MainFragmentInterface.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.main 2 | 3 | interface MainFragmentInterface { 4 | 5 | val position: Int? 6 | 7 | } -------------------------------------------------------------------------------- /modules/web/.prettierrc.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "$schema": "https://json.schemastore.org/prettierrc", 4 | "semi": false, 5 | "singleQuote": true, 6 | "arrowParens": "avoid" 7 | } 8 | -------------------------------------------------------------------------------- /app/src/debug/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | legado·D 3 | legado·D·search 4 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/InvalidBooksDirException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.exception 2 | 3 | class InvalidBooksDirException(msg: String) : NoStackTraceException(msg) 4 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/permission/OnErrorCallback.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.permission 2 | 3 | interface OnErrorCallback { 4 | 5 | fun onError(e: Exception) 6 | 7 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/constant/Status.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.constant 2 | 3 | object Status { 4 | const val STOP = 0 5 | const val PLAY = 1 6 | const val PAUSE = 3 7 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/read/page/entities/PageDirection.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.read.page.entities 2 | 3 | enum class PageDirection { 4 | NONE, PREV, NEXT 5 | } -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/domain/ManifestProperties.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib.domain; 2 | 3 | public interface ManifestProperties { 4 | 5 | String getName(); 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/EmptyFileException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.exception 2 | 3 | /** 4 | * 文件为空 5 | */ 6 | class EmptyFileException(msg: String) : NoStackTraceException(msg) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/TocEmptyException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.exception 2 | 3 | /** 4 | * 目录为空 5 | */ 6 | class TocEmptyException(msg: String) : NoStackTraceException(msg) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/IndexTag.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class IndexTag( 4 | val tagId: Int, 5 | val tagValues: List 6 | ) 7 | -------------------------------------------------------------------------------- /modules/web/src/hooks/loading.css: -------------------------------------------------------------------------------- 1 | .el-loading-spinner { 2 | font-size: 36px; 3 | color: #b5b5b5; 4 | } 5 | .el-loading-text { 6 | font-weight: 500; 7 | color: #b5b5b5 !important; 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/FdstHeader.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class FdstHeader( 4 | val magic: String, 5 | val numEntries: Int 6 | ) 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/objectpool/ObjectPoolExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.objectpool 2 | 3 | fun ObjectPool.synchronized(): ObjectPool = ObjectPoolLocked(this) 4 | -------------------------------------------------------------------------------- /modules/web/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] 2 | charset = utf-8 3 | indent_size = 2 4 | indent_style = space 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/ContentEmptyException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.exception 2 | 3 | /** 4 | * 内容为空 5 | */ 6 | class ContentEmptyException(msg: String) : NoStackTraceException(msg) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/decompress/CDICData.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.decompress 2 | 3 | class CDICEntry( 4 | var data: ByteArray, 5 | var decompressed: Boolean 6 | ) 7 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/RhinoContextFactory.kt: -------------------------------------------------------------------------------- 1 | package com.script 2 | 3 | import org.mozilla.javascript.ContextFactory 4 | 5 | open class RhinoContextFactory : ContextFactory() { 6 | 7 | } -------------------------------------------------------------------------------- /modules/web/src/assets/fonts/popfont.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | @font-face { 3 | font-family: 'FZZCYSK'; 4 | src: local('☺'), url('./popfont.ttf'); 5 | font-style: normal; 6 | font-weight: normal; 7 | } 8 | -------------------------------------------------------------------------------- /modules/web/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | 3 | export * from './bookStore' 4 | export * from './sourceStore' 5 | export * from './connectionStore' 6 | export default createPinia() 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/decompress/Decompressor.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.decompress 2 | 3 | interface Decompressor { 4 | 5 | fun decompress(data: ByteArray): ByteArray 6 | 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/manga/entities/BaseMangaPage.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.manga.entities 2 | 3 | interface BaseMangaPage { 4 | val chapterIndex: Int 5 | val index: Int 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceSort.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.source.manage 2 | 3 | enum class BookSourceSort { 4 | Default, Name, Url, Weight, Update, Enable, Respond 5 | } -------------------------------------------------------------------------------- /modules/web/src/assets/fonts/shelffont.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | @font-face { 3 | font-family: 'FZZCYSK'; 4 | src: local('☺'), url('./shelffont.ttf'); 5 | font-style: normal; 6 | font-weight: normal; 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/cronet/CallbackStep.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.cronet 2 | 3 | enum class CallbackStep { 4 | ON_READ_COMPLETED, 5 | ON_SUCCESS, 6 | ON_FAILED, 7 | ON_CANCELED 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/permission/OnPermissionsGrantedCallback.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.permission 2 | 3 | interface OnPermissionsGrantedCallback { 4 | 5 | fun onPermissionsGranted() 6 | 7 | } 8 | -------------------------------------------------------------------------------- /modules/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | } 10 | ], 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/ReadRecordShow.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | data class ReadRecordShow( 4 | var bookName: String, 5 | var readTime: Long, 6 | var lastRead: Long 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/KF8Resource.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class KF8Resource( 4 | val resourceType: String, 5 | val id: Int, 6 | val type: String 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/TOC.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class TOC( 4 | val label: String, 5 | val href: String, 6 | val subitems: List? = null 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/assets/privacyPolicy.md: -------------------------------------------------------------------------------- 1 | * 本应用没有服务端,不收集任何用户信息,只采用了Google Firebase收集崩溃报告和性能报告. 2 | * 本应用网络同步和备份采用webDav协议,由用户自己提供同步服务. 3 | * 存储权限用来打开本地文件和本地备份恢复. 4 | * 其它一些权限是Google Firebase需要. 5 | * 本应用为开源软件,内置js引擎,因书源调用js发生的任何问题由用户自行承担. -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/TagxHeader.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class TagxHeader( 4 | val magic: String, 5 | val length: Int, 6 | val numControlBytes: Int 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/model/localBook/README.md: -------------------------------------------------------------------------------- 1 | # 书籍文件导入解析 2 | 3 | * BaseLocalBookParse.kt 本地书籍解析接口 4 | * LocalBook.kt 导入解析总入口 5 | * TextFile.kt 解析txt 6 | * EpubFile.kt 解析epub 7 | * PdfFile.kt 解析pdf 纯图片形式 8 | * UmdFile.kt 解析umd -------------------------------------------------------------------------------- /app/src/main/assets/cronet.json: -------------------------------------------------------------------------------- 1 | {"x86":"2288814a4d9d4ee24154f52abf227fa0","armeabi-v7a":"ac8190c5e795d1a754b7bf2d477119c5","x86_64":"116f2d0f8e6363caacbd5c38bfc45b9f","arm64-v8a":"61a96a20241e56ac7ab107cc3e4c3fda","version":"128.0.6613.40"} -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/glide/progress/OnProgressListener.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.glide.progress 2 | 3 | typealias OnProgressListener = (isComplete: Boolean, percentage: Int, bytesRead: Long, totalBytes: Long) -> Unit 4 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/qrcode/ScanResultCallback.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.qrcode 2 | 3 | import com.google.zxing.Result 4 | 5 | interface ScanResultCallback { 6 | 7 | fun onScanResultCallback(result: Result?) 8 | 9 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/Ptagx.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class Ptagx( 4 | val tag: Int, 5 | val tagValueCount: Int, 6 | val valueCount: Int?, 7 | val valueBytes: Int? 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/TagxTag.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class TagxTag( 4 | val tag: Int, 5 | val numValues: Int, 6 | val bitmask: Int, 7 | val controlByte: Int, 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/service/README.md: -------------------------------------------------------------------------------- 1 | # android服务 2 | 3 | * AudioPlayService 音频播放服务 4 | * CheckSourceService 书源检测服务 5 | * DownloadService 缓存服务 6 | * HttpReadAloudService 在线朗读服务 7 | * TTSReadAloudService tts朗读服务 8 | * WebService web服务 -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/rhino/RhinoErrors.kt: -------------------------------------------------------------------------------- 1 | package com.script.rhino 2 | 3 | class RhinoInterruptError(override val cause: Throwable) : Error() 4 | 5 | class RhinoRecursionError(): Error("Maximum recursion depth exceeded.") 6 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/ConcurrentException.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package io.legado.app.exception 4 | 5 | /** 6 | * 并发限制 7 | */ 8 | class ConcurrentException(msg: String, val waitTime: Int) : NoStackTraceException(msg) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/ExthRecordType.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class ExthRecordType( 4 | val name: String, 5 | val type: String = "string", 6 | val many: Boolean = false 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/permission/OnPermissionsDeniedCallback.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.permission 2 | 3 | interface OnPermissionsDeniedCallback { 4 | 5 | fun onPermissionsDenied(deniedPermissions: Array) 6 | 7 | } 8 | -------------------------------------------------------------------------------- /modules/web/src/assets/sourceeditor.css: -------------------------------------------------------------------------------- 1 | @import './kbd.css'; 2 | @import './code.css'; 3 | 4 | body { 5 | padding: 0; 6 | margin: 0; 7 | } 8 | 9 | .el-tabs__header { 10 | position: sticky; 11 | top: 0px; 12 | z-index: 2; 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/objectpool/ObjectPool.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.objectpool 2 | 3 | interface ObjectPool { 4 | 5 | fun obtain(): T 6 | 7 | fun recycle(target: T) 8 | 9 | fun create(): T 10 | 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/NoBooksDirException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.exception 2 | 3 | import io.legado.app.R 4 | import splitties.init.appCtx 5 | 6 | class NoBooksDirException: NoStackTraceException(appCtx.getString(R.string.no_books_dir)) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/IndexData.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | import android.util.SparseArray 4 | 5 | data class IndexData( 6 | val table: List, 7 | val cncx: SparseArray 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_space_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /modules/web/src/assets/code.css: -------------------------------------------------------------------------------- 1 | code { 2 | border-radius: 4px; 3 | padding: 0.15rem 0.5rem; 4 | background-color: var(--el-fill-color-light); 5 | transition: 6 | color 0.25s, 7 | background-color 0.5s; 8 | font-size: 14px; 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/BookChapterExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | import io.legado.app.data.entities.BookChapter 4 | 5 | fun BookChapter.internString() { 6 | title = title.intern() 7 | bookUrl = bookUrl.intern() 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_item_focused_on_tv.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_circle_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/KF8Header.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class KF8Header( 4 | val fdst: Int, 5 | val numFdst: Int, 6 | val frag: Int, 7 | val skel: Int, 8 | val guide: Int, 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/PalmDocHeader.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class PalmDocHeader( 4 | val compression: Int, 5 | val numTextRecords: Int, 6 | val recordSize: Int, 7 | val encryption: Int 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/res/menu/file_long_click.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/menu/source_sub_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/README.md: -------------------------------------------------------------------------------- 1 | # 文件结构介绍 2 | 3 | * api 提供的接口 4 | * base 基类 5 | * constant 常量 6 | * data 数据 7 | * exception 错误类型 8 | * help 帮助 9 | * lib 库 10 | * model 解析 11 | * receiver 广播侦听 12 | * service 服务 13 | * ui 界面 14 | * utils 辅助类 15 | * web web服务 -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/ExecutorService.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help 2 | 3 | import java.util.concurrent.ExecutorService 4 | import java.util.concurrent.Executors 5 | 6 | val globalExecutor: ExecutorService by lazy { Executors.newSingleThreadExecutor() } 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/Skeleton.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class Skeleton( 4 | val index: Int, 5 | val name: String, 6 | val numFrag: Int, 7 | val offset: Int, 8 | val length: Int 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/manga/entities/MangaContent.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.manga.entities 2 | 3 | data class MangaContent( 4 | val pos: Int, 5 | val items: List, 6 | val curFinish: Boolean, 7 | val nextFinish: Boolean 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/res/menu/import_book_sel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/Fragment.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class Fragment( 4 | val insertOffset: Int, 5 | val selector: String, 6 | val index: Int, 7 | val offset: Int, 8 | val length: Int 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/MobiEntryHeaders.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class MobiEntryHeaders( 4 | val palmdoc: PalmDocHeader, 5 | val mobi: MobiHeader, 6 | val exth: Map, 7 | val kf8: KF8Header? 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/decompress/PlainDecompressor.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.decompress 2 | 3 | class PlainDecompressor : Decompressor { 4 | 5 | override fun decompress(data: ByteArray): ByteArray { 6 | return data 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_readbook_bottom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_readbook_bottom_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_readbook_top_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_readbook_top_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/VMBaseFragment.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base 2 | 3 | import androidx.lifecycle.ViewModel 4 | 5 | abstract class VMBaseFragment(layoutID: Int) : BaseFragment(layoutID) { 6 | 7 | protected abstract val viewModel: VM 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_fillet_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_pop_checkaddshelf_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Aug 27 18:19:17 CST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/IndexEntry.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | import android.util.SparseArray 4 | 5 | data class IndexEntry( 6 | val label: String, 7 | val tags: List, 8 | val tagMap: SparseArray 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_card_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_translucent_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/menu/source_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | local.properties 4 | .DS_Store 5 | /build 6 | build/ 7 | /captures 8 | .externalNativeBuild 9 | /release 10 | /tmp 11 | node_modules/ 12 | /app/app 13 | /app/google 14 | /app/gradle.properties 15 | package-lock.json 16 | .idea/ 17 | # Kotlin 2.0 18 | .kotlin/ 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_find_book_group.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_fillet_btn_press.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_popup_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/rhino/JavaObjectWrapFactory.kt: -------------------------------------------------------------------------------- 1 | package com.script.rhino 2 | 3 | import org.mozilla.javascript.Scriptable 4 | 5 | fun interface JavaObjectWrapFactory { 6 | 7 | fun wrap(scope: Scriptable?, javaObject: Any, staticType: Class<*>?): Scriptable 8 | 9 | } 10 | -------------------------------------------------------------------------------- /modules/web/src/pages/source/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from '@/App.vue' 3 | import sourceRouter from '@/router/sourceRouter' 4 | import store from '@/store' 5 | import 'element-plus/theme-chalk/dark/css-vars.css' 6 | 7 | createApp(App).use(store).use(sourceRouter).mount('#app') 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/dialogs/SelectItem.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.dialogs 2 | 3 | @Suppress("unused") 4 | data class SelectItem( 5 | val title: String, 6 | val value: T 7 | ) { 8 | 9 | override fun toString(): String { 10 | return title 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/KF6Section.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class KF6Section( 4 | val index: Int, 5 | val start: Int, 6 | val end: Int, 7 | val length: Int, 8 | val href: String, 9 | var next: KF6Section? = null 10 | ) 11 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.rss.favorites 2 | 3 | import android.app.Application 4 | import io.legado.app.base.BaseViewModel 5 | 6 | 7 | class RssFavoritesViewModel(application: Application) : BaseViewModel(application) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/widget/anima/explosion_field/OnAnimatorListener.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.widget.anima.explosion_field 2 | 3 | import android.animation.Animator 4 | import android.view.View 5 | 6 | interface OnAnimatorListener { 7 | fun onAnimationEnd(animator: Animator, view: View) 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/utils/BitwiseExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.utils 2 | 3 | internal infix fun Byte.and(mask: Int): Int = toInt() and mask 4 | 5 | internal infix fun Short.and(mask: Int): Int = toInt() and mask 6 | 7 | internal infix fun Int.and(mask: Long): Long = toLong() and mask 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/manga/entities/MangaChapter.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.manga.entities 2 | 3 | import io.legado.app.data.entities.BookChapter 4 | 5 | data class MangaChapter( 6 | val chapter: BookChapter, 7 | val pages: List, 8 | val imageCount: Int 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_shadow_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_text_cursor.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/objectpool/BaseSafeObjectPool.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.objectpool 2 | 3 | import androidx.core.util.Pools 4 | 5 | abstract class BaseSafeObjectPool(size: Int): BaseObjectPool(size) { 6 | 7 | override val pool = Pools.SynchronizedPool(size) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_shadow_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/permission/OnPermissionsResultCallback.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.permission 2 | 3 | interface OnPermissionsResultCallback { 4 | 5 | fun onPermissionsGranted() 6 | 7 | fun onPermissionsDenied(deniedPermissions: Array?) 8 | 9 | fun onError(e: Exception) 10 | 11 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_shadow_bottom_night.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_shadow_top_night.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_prefs_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/browsersupport/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes that help make an epub reader application. 3 | *

4 | * These classes have no dependencies on graphic toolkits, they're purely 5 | * to help with the browsing/navigation logic. 6 | */ 7 | package me.ag2s.epublib.browsersupport; 8 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/storage/BackupAES.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.storage 2 | 3 | import cn.hutool.crypto.symmetric.AES 4 | import io.legado.app.help.config.LocalConfig 5 | import io.legado.app.utils.MD5Utils 6 | 7 | class BackupAES : AES( 8 | MD5Utils.md5Encode(LocalConfig.password ?: "").encodeToByteArray(0, 16) 9 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_accent_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_log.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /modules/web/src/web.d.ts: -------------------------------------------------------------------------------- 1 | export type webReadConfig = { 2 | theme: number 3 | font: number 4 | fontSize: number 5 | readWidth: number 6 | infiniteLoading: boolean 7 | customFontName: string 8 | jumpDuration: number 9 | spacing: { 10 | paragraph: number 11 | line: number 12 | letter: number 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/adapter/animations/BaseAnimation.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base.adapter.animations 2 | 3 | import android.animation.Animator 4 | import android.view.View 5 | 6 | /** 7 | * adapter item 动画 8 | */ 9 | interface BaseAnimation { 10 | 11 | fun getAnimators(view: View): Array 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/webdav/WebDavException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.webdav 2 | 3 | open class WebDavException(msg: String) : Exception(msg) { 4 | 5 | override fun fillInStackTrace(): Throwable { 6 | return this 7 | } 8 | 9 | } 10 | 11 | class ObjectNotFoundException(msg: String) : WebDavException(msg) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/manga/entities/ReaderLoading.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.manga.entities 2 | 3 | data class ReaderLoading( 4 | override val chapterIndex: Int = 0, 5 | override val index: Int = 0, 6 | val mMessage: String? = null, 7 | val isVolume: Boolean = false 8 | ) : BaseMangaPage 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/recyclerview_divider_horizontal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_radius_1dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /modules/web/src/assets/bookshelf.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | height: 100vh; 5 | } 6 | 7 | #app { 8 | font-family: 'Avenir', Helvetica, Arial, sans-serif; 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | color: #2c3e50; 12 | margin: 0; 13 | height: 100%; 14 | } 15 | -------------------------------------------------------------------------------- /modules/web/src/assets/kbd.css: -------------------------------------------------------------------------------- 1 | kbd { 2 | align-items: center; 3 | background: rgba(125, 125, 125, 0.1); 4 | border-radius: 3px; 5 | border: 0; 6 | padding: 4px 5px; 7 | font-weight: bold; 8 | box-shadow: 9 | inset 0 -2px 0 0 #cdcde6, 10 | inset 0 0 1px 1px #fff, 11 | 0 1px 2px 1px rgba(30, 35, 90, 0.4); 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | **2022/10/02** 2 | 3 | * 更新cronet: 106.0.5249.79 4 | * 正文选择菜单朗读按钮长按可切换朗读选择内容和从选择开始处一直朗读 5 | * 源编辑输入框设置最大行数12,在行数特别多的时候更容易滚动到其它输入 6 | * 修复某些情况下无法搜索到标题的bug,净化规则较多的可能会降低搜索速度 by Xwite 7 | * 修复文件类书源换源后阅读bug by Xwite 8 | * Cronet 支持DnsHttpsSvcb by g2s20150909 9 | * 修复web进度同步问题 by 821938089 10 | * 启用混淆以减小app大小 有bug请带日志反馈 11 | * 其它一些优化 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_eink_border_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_radius_10dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/epub/HtmlProcessor.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib.epub; 2 | 3 | import java.io.OutputStream; 4 | 5 | import me.ag2s.epublib.domain.Resource; 6 | 7 | @SuppressWarnings("unused") 8 | public interface HtmlProcessor { 9 | 10 | void processHtmlResource(Resource resource, OutputStream out); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/glide/GlideHeaders.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.glide 2 | 3 | import com.bumptech.glide.load.model.Headers 4 | 5 | class GlideHeaders(private val headers: MutableMap) : Headers { 6 | 7 | override fun getHeaders(): MutableMap { 8 | return headers 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/canvasrecorder/pools/PicturePool.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.canvasrecorder.pools 2 | 3 | import android.graphics.Picture 4 | import io.legado.app.utils.objectpool.BaseObjectPool 5 | 6 | class PicturePool : BaseObjectPool(64) { 7 | 8 | override fun create(): Picture = Picture() 9 | 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_books.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_person.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/menu/dialog_text.xml: -------------------------------------------------------------------------------- 1 | 2 |

4 | 5 | 9 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/domain/LazyResourceProvider.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib.domain; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * @author jake 8 | */ 9 | public interface LazyResourceProvider { 10 | 11 | InputStream getResourceStream(String href) throws IOException; 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_explore.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/menu/theme_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/cronet/CallbackResult.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.cronet 2 | 3 | import org.chromium.net.CronetException 4 | 5 | import java.nio.ByteBuffer 6 | 7 | 8 | data class CallbackResult( 9 | val callbackStep: CallbackStep, 10 | val buffer: ByteBuffer? = null, 11 | val exception: CronetException? = null 12 | ) 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_rss_feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_fillet_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/permission/OnRequestPermissionsResultCallback.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.permission 2 | 3 | interface OnRequestPermissionsResultCallback { 4 | 5 | fun onRequestPermissionsResult(permissions: Array, grantResults: IntArray) 6 | 7 | fun onSettingActivityResult() 8 | 9 | fun onError(e: Exception) 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_play_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_reduce.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/launcher3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/launcher5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/config/ConfigTag.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.config 2 | 3 | object ConfigTag { 4 | 5 | const val OTHER_CONFIG = "otherConfig" 6 | const val THEME_CONFIG = "themeConfig" 7 | const val BACKUP_CONFIG = "backupConfig" 8 | const val COVER_CONFIG = "coverConfig" 9 | const val WELCOME_CONFIG = "welcomeConfig" 10 | 11 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_drop_up.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher4_b.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher7_b.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_stop_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/launcher1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/launcher2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/launcher4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/launcher6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_drop_down.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher5_b.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/app_update.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/theme_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_chapter_item_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/bookmark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/menu/qr_code_scan.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/Compilable.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Decompiled with CFR 0.152. 3 | */ 4 | package com.script 5 | 6 | import java.io.Reader 7 | 8 | interface Compilable { 9 | 10 | @Throws(ScriptException::class) 11 | fun compile(script: Reader): CompiledScript 12 | 13 | @Throws(ScriptException::class) 14 | fun compile(script: String): CompiledScript 15 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pause_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_skip_next.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_skip_previous.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/assets/web/help/md/SourceMRssHelp.md: -------------------------------------------------------------------------------- 1 | # 订阅源管理界面帮助 2 | 3 | * 订阅源可以通过规则订阅一些网络内容 4 | * 书源右上角标志 5 | * 绿点表示书源有发现,且启用了发现 6 | * 红点表示书源有发现,但是未启用 7 | * 没有标志表示此书源没有发现 8 | * 右上角有分组菜单,可以按分组筛选书源 9 | * 右上角更多菜单里包含 10 | * 新建订阅源 11 | * 本地导入 12 | * 网络导入 13 | * 二维码导入 14 | * 分享选中源 15 | * 选择源的更多操作在右下角的菜单里面,操作都是针对选择的书源 16 | * 启用所选 17 | * 禁用所选 18 | * 置顶所选 19 | * 置底所选 20 | * 导出所选 -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/coroutine/ActivelyCancelException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.coroutine 2 | 3 | import kotlin.coroutines.cancellation.CancellationException 4 | 5 | class ActivelyCancelException : CancellationException() { 6 | 7 | override fun fillInStackTrace(): Throwable { 8 | stackTrace = emptyArray() 9 | return this 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_sort_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_download.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fast_forward.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_common_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_source_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/adapter/ItemViewHolder.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base.adapter 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import androidx.viewbinding.ViewBinding 5 | 6 | /** 7 | * Created by Invincible on 2017/11/28. 8 | */ 9 | @Suppress("MemberVisibilityCanBePrivate") 10 | class ItemViewHolder(val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/Cookie.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.Index 5 | import androidx.room.PrimaryKey 6 | 7 | @Entity(tableName = "cookies", indices = [(Index(value = ["url"], unique = true))]) 8 | data class Cookie( 9 | @PrimaryKey 10 | var url: String = "", 11 | var cookie: String = "" 12 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_less.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/RssReadRecord.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "rssReadRecords") 7 | data class RssReadRecord( 8 | @PrimaryKey 9 | val record: String, 10 | val title: String? = null, 11 | val readTime: Long? = null, 12 | val read: Boolean = true 13 | ) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/rule/ExploreKind.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities.rule 2 | 3 | /** 4 | * 发现分类 5 | */ 6 | data class ExploreKind( 7 | val title: String = "", 8 | val url: String? = null, 9 | val style: FlexChildStyle? = null 10 | ) { 11 | 12 | fun style(): FlexChildStyle { 13 | return style ?: FlexChildStyle.defaultStyle 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_more.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fast_rewind.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/group_manage.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/servers.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/http/OkhttpUncaughtExceptionHandler.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.http 2 | 3 | import io.legado.app.constant.AppLog 4 | 5 | object OkhttpUncaughtExceptionHandler : Thread.UncaughtExceptionHandler { 6 | 7 | override fun uncaughtException(t: Thread, e: Throwable) { 8 | AppLog.put("Okhttp Dispatcher中的线程执行出错\n${e.localizedMessage}", e) 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/WindowInsetsExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | import androidx.core.view.WindowInsetsCompat 4 | 5 | val WindowInsetsCompat.navigationBarHeight 6 | get() = (getInsets(WindowInsetsCompat.Type.systemBars()).bottom - imeHeight).coerceAtLeast(0) 7 | 8 | val WindowInsetsCompat.imeHeight 9 | get() = getInsets(WindowInsetsCompat.Type.ime()).bottom 10 | -------------------------------------------------------------------------------- /modules/web/src/pages/bookshelf/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /modules/web/src/pages/source/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/MenuItemExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | import android.view.MenuItem 4 | import android.widget.ImageButton 5 | import androidx.annotation.DrawableRes 6 | import io.legado.app.R 7 | 8 | fun MenuItem.setIconCompat(@DrawableRes iconRes: Int) { 9 | setIcon(iconRes) 10 | actionView?.findViewById(R.id.item)?.setImageDrawable(icon) 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_action_button.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/menu/keyboard_assists_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/server_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/source_subscription.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/NCX.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class NCX( 4 | val index: Int, 5 | val offset: Int?, 6 | val size: Int?, 7 | val label: String, 8 | val headingLevel: Int?, 9 | val pos: List?, 10 | val parent: Int?, 11 | val firstChild: Int?, 12 | val lastChild: Int?, 13 | var children: List? = null 14 | ) 15 | -------------------------------------------------------------------------------- /app/src/main/res/menu/book_info_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /modules/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/constant/SourceType.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.constant 2 | 3 | import androidx.annotation.IntDef 4 | 5 | @Suppress("ConstPropertyName") 6 | object SourceType { 7 | 8 | const val book = 0 9 | const val rss = 1 10 | 11 | @Target(AnnotationTarget.VALUE_PARAMETER) 12 | @Retention(AnnotationRetention.SOURCE) 13 | @IntDef(book, rss) 14 | annotation class Type 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/Cache.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.Index 5 | import androidx.room.PrimaryKey 6 | 7 | @Entity(tableName = "caches", indices = [(Index(value = ["key"], unique = true))]) 8 | data class Cache( 9 | @PrimaryKey 10 | val key: String = "", 11 | var value: String? = null, 12 | var deadline: Long = 0L 13 | ) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/MobiMetadata.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class MobiMetadata( 4 | val identifier: String, 5 | val title: String, 6 | val author: List, 7 | val publisher: String, 8 | val language: String, 9 | val published: String, 10 | val description: String, 11 | val subject: List, 12 | val rights: String 13 | ) 14 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/MutableLiveDataExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import androidx.lifecycle.MutableLiveData 6 | 7 | private val mainHandler by lazy { Handler(Looper.getMainLooper()) } 8 | 9 | fun MutableLiveData.sendValue(value: T) { 10 | mainHandler.post { 11 | this@sendValue.value = value 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_down.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/README.md: -------------------------------------------------------------------------------- 1 | # 存储数据用 2 | 3 | * dao 数据操作 4 | * entities 数据模型 5 | * \Book 书籍信息 6 | * \BookChapter 目录信息 7 | * \BookGroup 书籍分组 8 | * \Bookmark 书签 9 | * \BookSource 书源 10 | * \Cookie http cookie 11 | * \ReplaceRule 替换规则 12 | * \RssArticle rss条目 13 | * \RssReadRecord rss阅读记录 14 | * \RssSource rss源 15 | * \RssStar rss收藏 16 | * \SearchBook 搜索结果 17 | * \SearchKeyword 搜索关键字 18 | * \TxtTocRule txt文件目录规则 19 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/coroutine/CoroutineContainer.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.coroutine 2 | 3 | internal interface CoroutineContainer { 4 | 5 | fun add(coroutine: Coroutine<*>): Boolean 6 | 7 | fun addAll(vararg coroutines: Coroutine<*>): Boolean 8 | 9 | fun remove(coroutine: Coroutine<*>): Boolean 10 | 11 | fun delete(coroutine: Coroutine<*>): Boolean 12 | 13 | fun clear() 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/manga/entities/MangaPage.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.manga.entities 2 | 3 | data class MangaPage( 4 | override val chapterIndex: Int = 0,//总章节位置 5 | val chapterSize: Int,//总章节数量 6 | val mImageUrl: String = "",//当前URL 7 | override val index: Int = 0,//当前章节位置 8 | var imageCount: Int = 0,//当前章节内容总数 9 | val mChapterName: String = "",//章节名称 10 | ) : BaseMangaPage 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_searchview.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_right.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/file_chooser.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/ScriptBindingsExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.script 2 | 3 | import org.mozilla.javascript.Context 4 | 5 | inline fun buildScriptBindings(block: (bindings: ScriptBindings) -> Unit): ScriptBindings { 6 | val bindings = ScriptBindings() 7 | Context.enter() 8 | try { 9 | block(bindings) 10 | } finally { 11 | Context.exit() 12 | } 13 | return bindings 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/assets/epub/chapter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Chapter 6 | 7 | 8 | 9 | 10 |

{title}

11 | {content} 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/KF8Section.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class KF8Section( 4 | val index: Int, 5 | val skeleton: Skeleton, 6 | val frags: List, 7 | val fragEnd: Int, 8 | val length: Int, 9 | val totalLength: Int, 10 | val href: String, 11 | var next: KF8Section? = null 12 | ) { 13 | val linear get() = frags.isNotEmpty() 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_star.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/search_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /modules/web/src/api/axios.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | /** @type {string} localStorage保存自定义阅读http服务接口的键值 */ 4 | export const baseURL_localStorage_key = 'remoteUrl' 5 | const SECOND = 1000 6 | 7 | const ajax = axios.create({ 8 | baseURL: 9 | import.meta.env.VITE_API || 10 | localStorage.getItem(baseURL_localStorage_key) || 11 | location.origin, 12 | timeout: 120 * SECOND, 13 | }) 14 | 15 | export default ajax 16 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/BookChapterReview.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | import android.os.Parcelable 4 | import androidx.room.ColumnInfo 5 | import kotlinx.parcelize.Parcelize 6 | 7 | @Parcelize 8 | class BookChapterReview( 9 | @ColumnInfo(defaultValue = "0") 10 | var bookId: Long = 0, 11 | var chapterId: Long = 0, 12 | var summaryUrl: String = "", 13 | ): Parcelable { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cursor_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/book/BookContent.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.book 2 | 3 | import io.legado.app.data.entities.ReplaceRule 4 | 5 | data class BookContent( 6 | val sameTitleRemoved: Boolean, 7 | val textList: List, 8 | //起效的替换规则 9 | val effectiveReplaceRules: List? 10 | ) { 11 | 12 | override fun toString(): String { 13 | return textList.joinToString("\n") 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/IndxHeader.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class IndxHeader( 4 | val magic: String, 5 | val length: Int, 6 | val type: Int, 7 | val idxt: Int, 8 | val numRecords: Int, 9 | val encoding: Int, 10 | val language: Int, 11 | val total: Int, 12 | val ordt: Int, 13 | val ligt: Int, 14 | val numLigt: Int, 15 | val numCncx: Int, 16 | ) 17 | -------------------------------------------------------------------------------- /app/src/main/res/color/selector_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_toc.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/app_log.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/assets/web/help/md/httpTTSHelp.md: -------------------------------------------------------------------------------- 1 | # 在线朗读规则说明 2 | 3 | * 在线朗读规则为url规则,同书源url 4 | * js参数 5 | ``` 6 | speakText //朗读文本 7 | speakSpeed //朗读速度,5-50 8 | ``` 9 | * 例: 10 | ``` 11 | http://tts.baidu.com/text2audio,{ 12 | "method": "POST", 13 | "body": "tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5003&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio" 14 | } 15 | ``` -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/widget/recycler/scroller/FastScrollStateChangeListener.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.widget.recycler.scroller 2 | 3 | interface FastScrollStateChangeListener { 4 | 5 | /** 6 | * Called when fast scrolling begins 7 | */ 8 | fun onFastScrollStart(fastScroller: FastScroller) 9 | 10 | /** 11 | * Called when fast scrolling ends 12 | */ 13 | fun onFastScrollStop(fastScroller: FastScroller) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/objectpool/ObjectPoolLocked.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.objectpool 2 | 3 | class ObjectPoolLocked(private val delegate: ObjectPool) : ObjectPool by delegate { 4 | 5 | @Synchronized 6 | override fun obtain(): T { 7 | return delegate.obtain() 8 | } 9 | 10 | @Synchronized 11 | override fun recycle(target: T) { 12 | return delegate.recycle(target) 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cursor_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/crash_log.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main_explore.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/assets/epub/intro.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Intro 6 | 7 | 8 | 9 | 10 |

内容简介

{intro} 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_swap_horiz.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/rss_read_record.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/exception/NoStackTraceException.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.exception 2 | 3 | /** 4 | * 不记录错误堆栈的报错 5 | */ 6 | open class NoStackTraceException(msg: String) : Exception(msg) { 7 | 8 | override fun fillInStackTrace(): Throwable { 9 | stackTrace = emptyStackTrace 10 | return this 11 | } 12 | 13 | companion object { 14 | private val emptyStackTrace = emptyArray() 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/rule/BookListRule.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities.rule 2 | 3 | /** 4 | * 书籍列表规则 5 | */ 6 | interface BookListRule { 7 | var bookList: String? 8 | var name: String? 9 | var author: String? 10 | var intro: String? 11 | var kind: String? 12 | var lastChapter: String? 13 | var updateTime: String? 14 | var bookUrl: String? 15 | var coverUrl: String? 16 | var wordCount: String? 17 | } -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/base/ThrowableUtils.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.base; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | 7 | public class ThrowableUtils { 8 | 9 | 10 | public static @NonNull 11 | IOException rethrowAsIOException(Throwable throwable) throws IOException { 12 | IOException newException = new IOException(throwable.getMessage(), throwable); 13 | throw newException; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/assets/web/help/md/debugHelp.md: -------------------------------------------------------------------------------- 1 | # 书源调试 2 | 3 | * 调试搜索>>输入关键字,如: 4 | ``` 5 | 系统 6 | ``` 7 | * 调试发现>>输入发现URL,如: 8 | ``` 9 | 月票榜::https://www.qidian.com/rank/yuepiao?page={{page}} 10 | ``` 11 | * 调试详情页>>输入详情页URL,如: 12 | ``` 13 | https://m.qidian.com/book/1015609210 14 | ``` 15 | * 调试目录页>>输入目录页URL,如: 16 | ``` 17 | ++https://www.zhaishuyuan.com/read/30394 18 | ``` 19 | * 调试正文页>>输入正文页URL,如: 20 | ``` 21 | --https://www.zhaishuyuan.com/chapter/30394/20940996 22 | ``` 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_explore_s.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /modules/web/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | 30 | *.tsbuildinfo 31 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/adapter/animations/SlideInBottomAnimation.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base.adapter.animations 2 | 3 | import android.animation.Animator 4 | import android.animation.ObjectAnimator 5 | import android.view.View 6 | 7 | class SlideInBottomAnimation : BaseAnimation { 8 | 9 | 10 | override fun getAnimators(view: View): Array = 11 | arrayOf(ObjectAnimator.ofFloat(view, "translationY", view.measuredHeight.toFloat(), 0f)) 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/PaintPool.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help 2 | 3 | import android.graphics.Paint 4 | import io.legado.app.utils.objectpool.BaseSafeObjectPool 5 | 6 | object PaintPool : BaseSafeObjectPool(8) { 7 | 8 | private val emptyPaint = Paint() 9 | 10 | override fun create(): Paint = Paint() 11 | 12 | override fun recycle(target: Paint) { 13 | target.set(emptyPaint) 14 | super.recycle(target) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/recyclerview_divider_vertical.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/menu/import_replace.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/io/legado/app/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app 2 | 3 | import org.junit.Assert.assertEquals 4 | import org.junit.Test 5 | 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | 14 | @Test 15 | fun addition_isCorrect() { 16 | assertEquals(4, 2 + 2) 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/Bindings.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Decompiled with CFR 0.152. 3 | */ 4 | package com.script 5 | 6 | interface Bindings : MutableMap { 7 | 8 | override fun containsKey(key: String): Boolean 9 | 10 | override operator fun get(key: String): Any? 11 | 12 | override fun put(key: String, value: Any?): Any? 13 | 14 | override fun putAll(from: Map) 15 | 16 | override fun remove(key: String): Any? 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/adapter/animations/SlideInLeftAnimation.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base.adapter.animations 2 | 3 | import android.animation.Animator 4 | import android.animation.ObjectAnimator 5 | import android.view.View 6 | 7 | 8 | class SlideInLeftAnimation : BaseAnimation { 9 | 10 | 11 | override fun getAnimators(view: View): Array = 12 | arrayOf(ObjectAnimator.ofFloat(view, "translationX", -view.rootView.width.toFloat(), 0f)) 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/adapter/animations/SlideInRightAnimation.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base.adapter.animations 2 | 3 | import android.animation.Animator 4 | import android.animation.ObjectAnimator 5 | import android.view.View 6 | 7 | 8 | class SlideInRightAnimation : BaseAnimation { 9 | 10 | 11 | override fun getAnimators(view: View): Array = 12 | arrayOf(ObjectAnimator.ofFloat(view, "translationX", view.rootView.width.toFloat(), 0f)) 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_folder.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_folder_open.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_tv_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/menu/replace_rule_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/rss_source_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/txt_toc_rule_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 简繁转化 4 | url: https://github.com/liuyueyi/quick-chinese-transfer/issues/new 5 | about: 简繁转化问题请优先到quick-chinese-transfer反馈 6 | - name: 讨论 / Discussions 7 | url: https://github.com/gedoor/legado/discussions 8 | about: Please ask and answer questions here. 9 | - name: 常见问题 / Wiki 10 | url: https://github.com/gedoor/legado/wiki 11 | about: Read wiki if your are new here. 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_storage_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /modules/web/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 | 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"], 12 | "@api": ["./src/api"], 13 | "@utils/*": ["./src/utils/*"] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/ConfigurationExtensions.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package io.legado.app.utils 4 | 5 | import android.content.res.Configuration 6 | import android.content.res.Resources 7 | 8 | val sysConfiguration: Configuration = Resources.getSystem().configuration 9 | 10 | val Configuration.isNightMode: Boolean 11 | get() { 12 | val mode = uiMode and Configuration.UI_MODE_NIGHT_MASK 13 | return mode == Configuration.UI_MODE_NIGHT_YES 14 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/Throttle.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | @Suppress("unused") 4 | class Throttle( 5 | wait: Long = 0L, 6 | leading: Boolean = true, 7 | trailing: Boolean = true, 8 | func: () -> T 9 | ) : Debounce(wait, wait, leading, trailing, func) 10 | 11 | fun throttle( 12 | wait: Long = 0L, 13 | leading: Boolean = true, 14 | trailing: Boolean = true, 15 | func: () -> T 16 | ) = Throttle(wait, leading, trailing, func) 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bookmark.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/save.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_img_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_close.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/code_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/menu/content_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main_my.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/menu/source_webview_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/rss/read/VisibleWebView.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.rss.read 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | import android.webkit.WebView 7 | 8 | class VisibleWebView( 9 | context: Context, 10 | attrs: AttributeSet? = null 11 | ) : WebView(context, attrs) { 12 | 13 | override fun onWindowVisibilityChanged(visibility: Int) { 14 | super.onWindowVisibilityChanged(View.VISIBLE) 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/view_title_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/book_group_manage.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /modules/web/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createWebHashHistory, createRouter } from 'vue-router' 2 | import { bookRoutes } from './bookRouter' 3 | import { sourceRoutes } from './sourceRouter' 4 | 5 | const router = createRouter({ 6 | // history: createWebHistory(process.env.BASE_URL), 7 | history: createWebHashHistory(), 8 | routes: [bookRoutes, sourceRoutes].flat(), 9 | }) 10 | 11 | router.afterEach(to => { 12 | if (to.name == 'shelf') document.title = '书架' 13 | }) 14 | 15 | export default router 16 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/ReadRecord.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | 6 | @Entity(tableName = "readRecord", primaryKeys = ["deviceId", "bookName"]) 7 | data class ReadRecord( 8 | var deviceId: String = "", 9 | var bookName: String = "", 10 | @ColumnInfo(defaultValue = "0") 11 | var readTime: Long = 0L, 12 | @ColumnInfo(defaultValue = "0") 13 | var lastRead: Long = System.currentTimeMillis() 14 | ) -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/import/remote/ServersViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.import.remote 2 | 3 | import android.app.Application 4 | import io.legado.app.base.BaseViewModel 5 | import io.legado.app.data.appDb 6 | import io.legado.app.data.entities.Server 7 | 8 | class ServersViewModel(application: Application): BaseViewModel(application) { 9 | 10 | 11 | fun delete(server: Server) { 12 | execute { 13 | appDb.serverDao.delete(server) 14 | } 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/widget/seekbar/SeekBarChangeListener.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.widget.seekbar 2 | 3 | import android.widget.SeekBar 4 | 5 | interface SeekBarChangeListener : SeekBar.OnSeekBarChangeListener { 6 | 7 | override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { 8 | 9 | } 10 | 11 | override fun onStartTrackingTouch(seekBar: SeekBar) { 12 | 13 | } 14 | 15 | override fun onStopTrackingTouch(seekBar: SeekBar) { 16 | 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/res/menu/font_select.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/import/local/ImportBook.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.import.local 2 | 3 | import io.legado.app.model.localBook.LocalBook 4 | import io.legado.app.utils.FileDoc 5 | 6 | data class ImportBook( 7 | val file: FileDoc, 8 | var isOnBookShelf: Boolean = !file.isDir && LocalBook.isOnBookShelf(file.name) 9 | ) { 10 | val name get() = file.name 11 | val isDir get() = file.isDir 12 | val size get() = file.size 13 | val lastModified get() = file.lastModified 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_folder_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lock_outline.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_number_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/menu/change_cover.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /modules/web/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*" 9 | ], 10 | "compilerOptions": { 11 | "composite": true, 12 | "noEmit": true, 13 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 14 | 15 | "module": "ESNext", 16 | "moduleResolution": "Bundler", 17 | "types": ["node"] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/assets/web/help/md/webDavHelp.md: -------------------------------------------------------------------------------- 1 | # WebDav备份教程 2 | 3 | ### 阅读支持云备份,采用WebDav协议,所有支持WebDav的云盘都可以,建议采用坚果云,每月免费1G流量,用来备份阅读足够了,下面就采用坚果云来讲解配置步骤. 4 | 5 | 1. 打开坚果云网站 https://www.jianguoyun.com/d/home#/ 6 | 2. 如果没有注册过坚果云先注册一下 7 | 3. 登录坚果云 8 | 4. 右上角用户名点开点账户信息 9 | 5. 点击安全选项 10 | 6. 在第三方管理里添加应用 11 | 7. 将应用示例里的服务器地址,用户名,和密码填到阅读的WebDav设置里 12 | 8. 阅读的WebDav配置在我的-备份与恢复,创建子文件夹选项保持默认即可 13 | 9. 设置完成后手动执行一下备份,看看是否成功 14 | 10. 恢复时选择想要恢复的备份文件 15 | 16 | ### 自动备份说明 17 | 18 | * 设置好备份之后每次退出App会自动进行备份 19 | * WebDav同一天的备份会覆盖,不同日期的备份不会覆盖 20 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/RuleSub.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "ruleSubs") 7 | data class RuleSub( 8 | @PrimaryKey 9 | val id: Long = System.currentTimeMillis(), 10 | var name: String = "", 11 | var url: String = "", 12 | var type: Int = 0, 13 | var customOrder: Int = 0, 14 | var autoUpdate: Boolean = false, 15 | var update: Long = System.currentTimeMillis() 16 | ) 17 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/manga/config/MangaColorFilterConfig.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.manga.config 2 | 3 | import io.legado.app.utils.GSON 4 | 5 | data class MangaColorFilterConfig( 6 | var r: Int = 0, 7 | var g: Int = 0, 8 | var b: Int = 0, 9 | var a: Int = 0, 10 | var l: Int = 0 11 | ) { 12 | fun toJson(): String { 13 | if (r == 0 && g == 0 && b == 0 && a == 0 && l == 0) { 14 | return "" 15 | } 16 | return GSON.toJson(this) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_backup.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_exit.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_vert.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_title_bar_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/domain/ManifestItemRefProperties.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib.domain; 2 | 3 | @SuppressWarnings("unused") 4 | public enum ManifestItemRefProperties implements ManifestProperties { 5 | PAGE_SPREAD_LEFT("page-spread-left"), 6 | PAGE_SPREAD_RIGHT("page-spread-right"); 7 | 8 | private final String name; 9 | 10 | ManifestItemRefProperties(String name) { 11 | this.name = name; 12 | } 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /modules/web/src/pages/source/README.md: -------------------------------------------------------------------------------- 1 | # legado_web_editor 2 | 3 | ## 🚧开发注意 4 | 5 | 如果你想要调试项目 请修改文件`.env.development`里`VITE_API`为阅读web服务ip 6 | 7 | ## 路由 8 | 9 | /rssSource 订阅源编辑 10 | /rssSource 书源编辑 11 | 12 | ## 🎨Project setup 13 | 14 | ``` 15 | pnpm i 16 | ``` 17 | 18 | ### Compiles and hot-reloads for development 19 | 20 | ``` 21 | pnpm dev 22 | ``` 23 | 24 | ### Compiles and minifies for production 25 | 26 | ``` 27 | pnpm build 28 | ``` 29 | 30 | ### Lints and fixes files 31 | 32 | ``` 33 | pnpm lint:fix 34 | ``` 35 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/theme/view/ThemeProgressBar.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.theme.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.widget.ProgressBar 6 | import io.legado.app.lib.theme.accentColor 7 | import io.legado.app.utils.applyTint 8 | 9 | class ThemeProgressBar(context: Context, attrs: AttributeSet) : ProgressBar(context, attrs) { 10 | 11 | init { 12 | if (!isInEditMode) { 13 | applyTint(context.accentColor) 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/AsyncFileHandler.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | import io.legado.app.help.globalExecutor 4 | import java.util.logging.FileHandler 5 | import java.util.logging.LogRecord 6 | 7 | class AsyncFileHandler(pattern: String) : FileHandler(pattern) { 8 | 9 | override fun publish(record: LogRecord?) { 10 | if (!isLoggable(record)) { 11 | return 12 | } 13 | globalExecutor.execute { 14 | super.publish(record) 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/objectpool/BaseObjectPool.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.objectpool 2 | 3 | import androidx.annotation.CallSuper 4 | import androidx.core.util.Pools 5 | 6 | abstract class BaseObjectPool(size: Int) : ObjectPool { 7 | 8 | open val pool = Pools.SimplePool(size) 9 | 10 | override fun obtain(): T { 11 | return pool.acquire() ?: create() 12 | } 13 | 14 | @CallSuper 15 | override fun recycle(target: T) { 16 | pool.release(target) 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pause_outline_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 14 | -------------------------------------------------------------------------------- /modules/web/src/pages/bookshelf/README.md: -------------------------------------------------------------------------------- 1 | # 「阅读3.0」 web 端(已打包进阅读3.0,不能设置IP) 2 | 3 | 本程序为「阅读3.0」的配套 web 端,需要保证手机和电脑在同一局域网内,然后手机端打开 web 服务。 4 | 5 | ~~在线地址 http://alanskycn.gitee.io/vip/reader/~~ 6 | 7 | ## 具体实现 8 | 9 | 使用 Vue3 开发 10 | 11 | ## 功能特性 12 | 13 | - 本地存储阅读记录与设置 14 | - 阅读主题切换 15 | - 夜间模式 16 | - 字号调节 17 | - 字体调节 18 | - 阅读宽度调节 19 | 20 | ## 使用方法 21 | 22 | ```shell 23 | pnpm install 24 | #安装项目 25 | pnpm dev 26 | #开发模式 27 | pnpm build 28 | #打包 29 | pnpm lint:fix 30 | #格式化代码 31 | ``` 32 | 33 | - 调试的时候可以修改.env.development里面的地址连接手机端调试 34 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/widget/recycler/VerticalDivider.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.widget.recycler 2 | 3 | import android.content.Context 4 | import androidx.core.content.ContextCompat 5 | import androidx.recyclerview.widget.DividerItemDecoration 6 | import io.legado.app.R 7 | 8 | class VerticalDivider(context: Context) : DividerItemDecoration(context, VERTICAL) { 9 | 10 | init { 11 | ContextCompat.getDrawable(context, R.drawable.ic_divider)?.let { 12 | this.setDrawable(it) 13 | } 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_star_border.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/assets/web/vue/assets/loading-6mEK85yy.js: -------------------------------------------------------------------------------- 1 | import{ak as i,D as g,N as c,a9 as d,al as f,u as m}from"./vendor-DYWUNZmw.js";const L=(s,t,l=i)=>{const a=g(!1);let r=null;const o=()=>a.value=!1,n=()=>a.value=!0;c(a,e=>{if(!e)return r==null?void 0:r.close();r=f.service({target:m(s),spinner:l,text:t,lock:!0,background:"rgba(0, 0, 0, 0)"})});const u=e=>{if(!(e instanceof Promise))throw TypeError("loadingWrapper argument must be Promise");return n(),e.finally(o)};return d(()=>{o()}),{isLoading:a,showLoading:n,closeLoading:o,loadingWrapper:u}};export{L as u}; 2 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/read/page/provider/LayoutProgressListener.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.read.page.provider 2 | 3 | import io.legado.app.ui.book.read.page.entities.TextPage 4 | 5 | interface LayoutProgressListener { 6 | 7 | /** 8 | * 单页排版完成 9 | */ 10 | fun onLayoutPageCompleted(index: Int, page: TextPage) {} 11 | 12 | /** 13 | * 全部排版完成 14 | */ 15 | fun onLayoutCompleted() {} 16 | 17 | /** 18 | * 排版出现异常 19 | */ 20 | fun onLayoutException(e: Throwable) {} 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_eink_border_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_person_s.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/theme/view/ThemeCheckBox.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.theme.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.appcompat.widget.AppCompatCheckBox 6 | import io.legado.app.lib.theme.accentColor 7 | import io.legado.app.utils.applyTint 8 | 9 | class ThemeCheckBox(context: Context, attrs: AttributeSet) : AppCompatCheckBox(context, attrs) { 10 | 11 | init { 12 | if (!isInEditMode) { 13 | applyTint(context.accentColor) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/AnimationExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | import android.content.Context 4 | import android.view.animation.Animation 5 | import android.view.animation.AnimationUtils 6 | import androidx.annotation.AnimRes 7 | import io.legado.app.help.config.AppConfig 8 | 9 | fun loadAnimation(context: Context, @AnimRes id: Int): Animation { 10 | val animation = AnimationUtils.loadAnimation(context, id) 11 | if (AppConfig.isEInkMode) { 12 | animation.duration = 0 13 | } 14 | return animation 15 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_volume_up.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/browsersupport/NavigationEventListener.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib.browsersupport; 2 | 3 | /** 4 | * Implemented by classes that want to be notified if the user moves to 5 | * another location in the book. 6 | * 7 | * @author paul 8 | */ 9 | public interface NavigationEventListener { 10 | 11 | /** 12 | * Called whenever the user navigates to another position in the book. 13 | * 14 | * @param navigationEvent f 15 | */ 16 | void navigationPerformed(NavigationEvent navigationEvent); 17 | } -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/umdlib/domain/UmdEnd.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.umdlib.domain; 2 | 3 | import java.io.IOException; 4 | 5 | import me.ag2s.umdlib.tool.WrapOutputStream; 6 | 7 | /** 8 | * End part of UMD book, nothing to be special 9 | * 10 | * @author Ray Liang (liangguanhui@qq.com) 11 | * 2009-12-20 12 | */ 13 | public class UmdEnd { 14 | 15 | public void buildEnd(WrapOutputStream wos) throws IOException { 16 | wos.writeBytes('#', 0x0C, 0, 0x01, 0x09); 17 | wos.writeInt(wos.getWritten() + 4); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_eink_border_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/Constants.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib; 2 | 3 | 4 | public interface Constants { 5 | 6 | String CHARACTER_ENCODING = "UTF-8"; 7 | String DOCTYPE_XHTML = ""; 8 | String NAMESPACE_XHTML = "http://www.w3.org/1999/xhtml"; 9 | String EPUB_GENERATOR_NAME = "Ag2S EpubLib"; 10 | String EPUB_DUOKAN_NAME = "DK-SONGTI"; 11 | char FRAGMENT_SEPARATOR_CHAR = '#'; 12 | String DEFAULT_TOC_ID = "toc"; 13 | } 14 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/epub/BookProcessor.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib.epub; 2 | 3 | import me.ag2s.epublib.domain.EpubBook; 4 | 5 | /** 6 | * Post-processes a book. 7 | *

8 | * Can be used to clean up a book after reading or before writing. 9 | * 10 | * @author paul 11 | */ 12 | public interface BookProcessor { 13 | 14 | /** 15 | * A BookProcessor that returns the input book unchanged. 16 | */ 17 | BookProcessor IDENTITY_BOOKPROCESSOR = book -> book; 18 | 19 | EpubBook processBook(EpubBook book); 20 | } 21 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/Invocable.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Decompiled with CFR 0.152. 3 | */ 4 | package com.script 5 | 6 | interface Invocable { 7 | fun getInterface(clazz: Class): T? 8 | 9 | fun getInterface(obj: Any?, paramClass: Class): T? 10 | 11 | @Throws(ScriptException::class, NoSuchMethodException::class) 12 | fun invokeFunction(name: String, vararg args: Any): Any? 13 | 14 | @Throws(ScriptException::class, NoSuchMethodException::class) 15 | fun invokeMethod(obj: Any?, name: String, vararg args: Any): Any? 16 | } -------------------------------------------------------------------------------- /modules/web/src/plugins/jump.d.ts: -------------------------------------------------------------------------------- 1 | export {} 2 | export type Options = { 3 | duration?: number | [(distance: number) => number] 4 | offset?: number 5 | callback?: () => void // "undefined" is a suitable default, and won't be called 6 | easing?: ( 7 | timeElapsed: number, 8 | start: number, 9 | distance: number, 10 | duration: number, 11 | ) => number 12 | a11y?: boolean 13 | container?: HTMLElement | string 14 | } 15 | export default function ( 16 | target: number | string | HTMLElement, 17 | options: Options = {}, 18 | ): void 19 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/constant/NotificationId.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.constant 2 | 3 | /** 4 | * 通知ID不能重复,统一规划通知ID 5 | */ 6 | @Suppress("ConstPropertyName") 7 | object NotificationId { 8 | 9 | const val ReadAloudService = 101 10 | const val AudioPlayService = 102 11 | const val CacheBookService = 103 12 | const val ExportBookService = 104 13 | const val WebService = 105 14 | const val DownloadService = 106 15 | const val CheckSourceService = 107 16 | const val Download = 10000 17 | const val ExportBook = 201 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /modules/web/src/router/bookRouter.ts: -------------------------------------------------------------------------------- 1 | import { createWebHashHistory, createRouter } from 'vue-router' 2 | 3 | export const bookRoutes = [ 4 | { 5 | path: '/', 6 | name: 'shelf', 7 | component: () => import('../views/BookShelf.vue'), 8 | }, 9 | { 10 | path: '/chapter', 11 | name: 'chapter', 12 | component: () => import('../views/BookChapter.vue'), 13 | }, 14 | ] 15 | 16 | const router = createRouter({ 17 | // mode: "history", 18 | history: createWebHashHistory(), 19 | routes: bookRoutes, 20 | }) 21 | 22 | export default router 23 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/canvasrecorder/CanvasRecorder.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.canvasrecorder 2 | 3 | import android.graphics.Canvas 4 | 5 | interface CanvasRecorder { 6 | 7 | val width: Int 8 | 9 | val height: Int 10 | 11 | fun beginRecording(width: Int, height: Int): Canvas 12 | 13 | fun endRecording() 14 | 15 | fun draw(canvas: Canvas) 16 | 17 | fun invalidate() 18 | 19 | fun recycle() 20 | 21 | fun isDirty(): Boolean 22 | 23 | fun isLocked(): Boolean 24 | 25 | fun needRecord(): Boolean 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/theme/view/ThemeRadioButton.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.theme.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.appcompat.widget.AppCompatRadioButton 6 | import io.legado.app.lib.theme.accentColor 7 | import io.legado.app.utils.applyTint 8 | 9 | class ThemeRadioButton(context: Context, attrs: AttributeSet) : 10 | AppCompatRadioButton(context, attrs) { 11 | 12 | init { 13 | if (!isInEditMode) { 14 | applyTint(context.accentColor) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/model/Download.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.model 2 | 3 | import android.content.Context 4 | import io.legado.app.constant.IntentAction 5 | import io.legado.app.service.DownloadService 6 | import io.legado.app.utils.startService 7 | 8 | object Download { 9 | 10 | 11 | fun start(context: Context, url: String, fileName: String) { 12 | context.startService { 13 | action = IntentAction.start 14 | putExtra("url", url) 15 | putExtra("fileName", fileName) 16 | } 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/widget/text/PrimaryTextView.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.widget.text 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.appcompat.widget.AppCompatTextView 6 | import io.legado.app.lib.theme.ThemeStore 7 | 8 | /** 9 | * @author Aidan Follestad (afollestad) 10 | */ 11 | @Suppress("unused") 12 | class PrimaryTextView(context: Context, attrs: AttributeSet) : 13 | AppCompatTextView(context, attrs) { 14 | 15 | init { 16 | setTextColor(ThemeStore.textColorPrimary(context)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_create_folder_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_tab_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/widget/text/SecondaryTextView.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.widget.text 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.appcompat.widget.AppCompatTextView 6 | import io.legado.app.lib.theme.secondaryTextColor 7 | 8 | /** 9 | * @author Aidan Follestad (afollestad) 10 | */ 11 | @Suppress("unused") 12 | class SecondaryTextView(context: Context, attrs: AttributeSet) : 13 | AppCompatTextView(context, attrs) { 14 | 15 | init { 16 | setTextColor(context.secondaryTextColor) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/constant/BookSourceType.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.constant 2 | 3 | import androidx.annotation.IntDef 4 | 5 | @Suppress("ConstPropertyName") 6 | object BookSourceType { 7 | 8 | const val default = 0 // 0 文本 9 | const val audio = 1 // 1 音频 10 | const val image = 2 // 2 图片 11 | const val file = 3 // 3 只提供下载服务的网站 12 | 13 | @Target(AnnotationTarget.VALUE_PARAMETER) 14 | @Retention(AnnotationRetention.SOURCE) 15 | @IntDef(default, audio, image, file) 16 | annotation class Type 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/rss/article/BaseRssArticlesAdapter.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.rss.article 2 | 3 | import android.content.Context 4 | import androidx.viewbinding.ViewBinding 5 | import io.legado.app.base.adapter.RecyclerAdapter 6 | import io.legado.app.data.entities.RssArticle 7 | 8 | 9 | abstract class BaseRssArticlesAdapter(context: Context, val callBack: CallBack) : 10 | RecyclerAdapter(context) { 11 | 12 | interface CallBack { 13 | val isGridLayout: Boolean 14 | fun readRss(rssArticle: RssArticle) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/item_radio_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/menu/rss_main_item.xml: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 7 | 8 | 11 | 12 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /modules/web/src/pages/bookshelf/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from '@/App.vue' 3 | import bookRouter from '@/router/bookRouter' 4 | import store from '@/store' 5 | import 'element-plus/theme-chalk/dark/css-vars.css' 6 | 7 | createApp(App).use(store).use(bookRouter).mount('#app') 8 | 9 | // 同步Element PLUS 夜间模式 10 | watch( 11 | () => useBookStore().isNight, 12 | isNight => { 13 | if (isNight) { 14 | document.documentElement.classList.add('dark') 15 | } else { 16 | document.documentElement.classList.remove('dark') 17 | } 18 | }, 19 | ) 20 | -------------------------------------------------------------------------------- /modules/web/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import pluginVue from 'eslint-plugin-vue' 2 | import vueTsEslintConfig from '@vue/eslint-config-typescript' 3 | import skipFormatting from '@vue/eslint-config-prettier/skip-formatting' 4 | 5 | export default [ 6 | { 7 | name: 'app/files-to-lint', 8 | files: ['**/*.{ts,mts,tsx,vue}'], 9 | }, 10 | 11 | { 12 | name: 'app/files-to-ignore', 13 | ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**', "src/plugins/jump.js"], 14 | }, 15 | 16 | ...pluginVue.configs['flat/essential'], 17 | ...vueTsEslintConfig(), 18 | skipFormatting, 19 | ] 20 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/read/page/entities/column/BaseColumn.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.read.page.entities.column 2 | 3 | import android.graphics.Canvas 4 | import io.legado.app.ui.book.read.page.ContentTextView 5 | import io.legado.app.ui.book.read.page.entities.TextLine 6 | 7 | /** 8 | * 列基类 9 | */ 10 | interface BaseColumn { 11 | var start: Float 12 | var end: Float 13 | var textLine: TextLine 14 | 15 | fun draw(view: ContentTextView, canvas: Canvas) 16 | 17 | fun isTouch(x: Float): Boolean { 18 | return x > start && x < end 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/VMBaseActivity.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.viewbinding.ViewBinding 5 | import io.legado.app.constant.Theme 6 | 7 | abstract class VMBaseActivity( 8 | fullScreen: Boolean = true, 9 | theme: Theme = Theme.Auto, 10 | toolBarTheme: Theme = Theme.Auto, 11 | transparent: Boolean = false, 12 | imageBg: Boolean = true 13 | ) : BaseActivity(fullScreen, theme, toolBarTheme, transparent, imageBg) { 14 | 15 | protected abstract val viewModel: VM 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/rule/RowUi.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities.rule 2 | 3 | data class RowUi( 4 | var name: String = "", 5 | var type: String = "text", 6 | var action: String? = null, 7 | var style: FlexChildStyle? = null 8 | ) { 9 | 10 | @Suppress("ConstPropertyName") 11 | object Type { 12 | 13 | const val text = "text" 14 | const val password = "password" 15 | const val button = "button" 16 | 17 | } 18 | 19 | fun style(): FlexChildStyle { 20 | return style ?: FlexChildStyle.defaultStyle 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/ThrowableExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils 2 | 3 | import java.io.IOException 4 | 5 | val Throwable.stackTraceStr: String 6 | get() { 7 | val stackTrace = stackTraceToString() 8 | val lMsg = this.localizedMessage ?: "noErrorMsg" 9 | return when { 10 | stackTrace.isNotEmpty() -> stackTrace 11 | else -> lMsg 12 | } 13 | } 14 | 15 | fun Throwable.asIOException(): IOException { 16 | val newException = IOException(this.message) 17 | newException.initCause(this) 18 | return newException 19 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/canvasrecorder/pools/CanvasPool.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.canvasrecorder.pools 2 | 3 | import android.graphics.Canvas 4 | import androidx.core.util.Pools 5 | 6 | class CanvasPool(size: Int) { 7 | 8 | private val pool = Pools.SynchronizedPool(size) 9 | 10 | fun obtain(): Canvas { 11 | val canvas = pool.acquire() ?: Canvas() 12 | return canvas 13 | } 14 | 15 | fun recycle(canvas: Canvas) { 16 | canvas.setBitmap(null) 17 | canvas.restoreToCount(1) 18 | pool.release(canvas) 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_delete.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_restore.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/assets/web/help/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | help 6 | 7 | 8 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/model/localBook/BaseLocalBookParse.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.model.localBook 2 | 3 | import io.legado.app.data.entities.Book 4 | import io.legado.app.data.entities.BookChapter 5 | import java.io.InputStream 6 | 7 | /** 8 | *companion object interface 9 | *see EpubFile.kt 10 | */ 11 | interface BaseLocalBookParse { 12 | 13 | fun upBookInfo(book: Book) 14 | 15 | fun getChapterList(book: Book): ArrayList 16 | 17 | fun getContent(book: Book, chapter: BookChapter): String? 18 | 19 | fun getImage(book: Book, href: String): InputStream? 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/README.md: -------------------------------------------------------------------------------- 1 | # 放置与界面有关的类 2 | 3 | * about 关于界面 4 | * association 导入书源界面 5 | * book\audio 音频播放界面 6 | * book\arrange 书架整理界面 7 | * book\info 书籍信息查看 8 | * book\read 书籍阅读界面 9 | * book\search 搜索书籍界面 10 | * book\source 书源界面 11 | * book\changeCover 封面换源界面 12 | * book\changeSource 换源界面 13 | * book\toc 目录界面 14 | * book\download 下载界面 15 | * book\explore 发现界面 16 | * book\local 书籍导入界面 17 | * document 文件选择界面 18 | * config 配置界面 19 | * main 主界面 20 | * qrCode 二维码扫描界面 21 | * replaceRule 替换净化界面 22 | * rss\article 订阅条目界面 23 | * rss\read 订阅阅读界面 24 | * rss\source 订阅源界面 25 | * welcome 欢迎界面 26 | * widget 自定义插件 -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/http/OkHttpExceptionInterceptor.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.http 2 | 3 | import okhttp3.Interceptor 4 | import okhttp3.Response 5 | import java.io.IOException 6 | 7 | object OkHttpExceptionInterceptor : Interceptor { 8 | 9 | @Throws(IOException::class) 10 | override fun intercept(chain: Interceptor.Chain): Response { 11 | try { 12 | return chain.proceed(chain.request()) 13 | } catch (e: IOException) { 14 | throw e 15 | } catch (e: Throwable) { 16 | throw IOException(e) 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/theme/view/ThemeSeekBar.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.theme.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.appcompat.widget.AppCompatSeekBar 6 | import io.legado.app.lib.theme.accentColor 7 | import io.legado.app.utils.applyTint 8 | 9 | /** 10 | * @author Aidan Follestad (afollestad) 11 | */ 12 | class ThemeSeekBar(context: Context, attrs: AttributeSet) : AppCompatSeekBar(context, attrs) { 13 | 14 | init { 15 | if (!isInEditMode) { 16 | applyTint(context.accentColor) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/theme/view/ThemeSwitch.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.theme.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.appcompat.widget.SwitchCompat 6 | import io.legado.app.lib.theme.accentColor 7 | import io.legado.app.utils.applyTint 8 | 9 | /** 10 | * @author Aidan Follestad (afollestad) 11 | */ 12 | class ThemeSwitch(context: Context, attrs: AttributeSet) : SwitchCompat(context, attrs) { 13 | 14 | init { 15 | if (!isInEditMode) { 16 | applyTint(context.accentColor) 17 | } 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/base/adapter/animations/AlphaInAnimation.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.base.adapter.animations 2 | 3 | import android.animation.Animator 4 | import android.animation.ObjectAnimator 5 | import android.view.View 6 | 7 | 8 | class AlphaInAnimation @JvmOverloads constructor(private val mFrom: Float = DEFAULT_ALPHA_FROM) : 9 | BaseAnimation { 10 | 11 | override fun getAnimators(view: View): Array = 12 | arrayOf(ObjectAnimator.ofFloat(view, "alpha", mFrom, 1f)) 13 | 14 | companion object { 15 | 16 | private const val DEFAULT_ALPHA_FROM = 0f 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/popup_keyboard_tool.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/menu/book_search_scope.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/menu/rss_source_debug.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/constant/PageAnim.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.constant 2 | 3 | import androidx.annotation.IntDef 4 | 5 | @Suppress("ConstPropertyName") 6 | object PageAnim { 7 | 8 | const val coverPageAnim = 0 9 | 10 | const val slidePageAnim = 1 11 | 12 | const val simulationPageAnim = 2 13 | 14 | const val scrollPageAnim = 3 15 | 16 | const val noAnim = 4 17 | 18 | @Target(AnnotationTarget.VALUE_PARAMETER) 19 | @Retention(AnnotationRetention.SOURCE) 20 | @IntDef(coverPageAnim, slidePageAnim, simulationPageAnim, scrollPageAnim, noAnim) 21 | annotation class Anim 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/widget/image/ImageButton.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.widget.image 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.appcompat.widget.AppCompatImageView 6 | 7 | class ImageButton @JvmOverloads constructor( 8 | context: Context, 9 | attrs: AttributeSet? = null 10 | ) : AppCompatImageView(context, attrs) { 11 | 12 | 13 | override fun setEnabled(enabled: Boolean) { 14 | if (isEnabled != enabled) { 15 | imageAlpha = if (enabled) 0xFF else 0x3F 16 | } 17 | super.setEnabled(enabled) 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_scoring.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /modules/web/src/router/sourceRouter.ts: -------------------------------------------------------------------------------- 1 | import sourceEditor from '../views/SourceEditor.vue' 2 | import { createWebHashHistory, createRouter } from 'vue-router' 3 | 4 | export const sourceRoutes = [ 5 | { 6 | path: '/bookSource', 7 | name: 'book-home', 8 | component: sourceEditor, 9 | }, 10 | { 11 | path: '/rssSource', 12 | name: 'rss-home', 13 | component: sourceEditor, 14 | }, 15 | ] 16 | 17 | const router = createRouter({ 18 | // history: createWebHistory(process.env.BASE_URL), 19 | history: createWebHashHistory(), 20 | routes: sourceRoutes, 21 | }) 22 | 23 | export default router 24 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/permission/RequestPlugins.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.permission 2 | 3 | internal object RequestPlugins { 4 | 5 | @Volatile 6 | var sRequestCallback: OnRequestPermissionsResultCallback? = null 7 | 8 | @Volatile 9 | var sResultCallback: OnPermissionsResultCallback? = null 10 | 11 | fun setOnRequestPermissionsCallback(callback: OnRequestPermissionsResultCallback) { 12 | sRequestCallback = callback 13 | } 14 | 15 | fun setOnPermissionsResultCallback(callback: OnPermissionsResultCallback) { 16 | sResultCallback = callback 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/assets/web/help/md/SourceMBookHelp.md: -------------------------------------------------------------------------------- 1 | # 书源管理界面帮助 2 | 3 | * 书源右上角标志 4 | * 绿点表示书源有发现,且启用了发现 5 | * 红点表示书源有发现,但是未启用 6 | * 没有标志表示此书源没有发现 7 | * 右上角有分组菜单,可以按分组筛选书源 8 | * 右上角更多菜单里包含 9 | * 新建书源 10 | * 本地导入 11 | * 网络导入 12 | * 二维码导入 13 | * 分享选中源 14 | * 选择源的更多操作在右下角的菜单里面,操作都是针对选择的书源 15 | * 启用所选 16 | * 禁用所选 17 | * 添加分组 18 | * 移除分组 19 | * 启用发现 20 | * 禁用发现 21 | * 置顶所选 22 | * 置底所选 23 | * 导出所选 24 | * 校验所选 25 | * 校验书源可批量校验书源,由于网络等原因结果仅限参考 26 | * "校验成功"是指所选的校验项目全部通过 27 | * 可正常识别搜索为空、发现为空、搜索(发现)目录为空、搜索(发现)正文为空、校验超时、js执行错误导致的失效,其余的原因视为网站失效 28 | * 校验搜索优先使用书源填写的校验关键词,不存在时使用用户输入的关键词 29 | * 校验结束后会自动筛选"失效"书源 -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/canvasrecorder/pools/RenderNodePool.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.utils.canvasrecorder.pools 2 | 3 | import android.graphics.RenderNode 4 | import android.os.Build 5 | import androidx.annotation.RequiresApi 6 | import io.legado.app.utils.objectpool.BaseObjectPool 7 | 8 | @RequiresApi(Build.VERSION_CODES.Q) 9 | class RenderNodePool : BaseObjectPool(64) { 10 | 11 | override fun recycle(target: RenderNode) { 12 | target.discardDisplayList() 13 | super.recycle(target) 14 | } 15 | 16 | override fun create(): RenderNode = RenderNode("CanvasRecorder") 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sort.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/open_url_confirm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /modules/book/src/main/java/me/ag2s/epublib/domain/ManifestItemProperties.java: -------------------------------------------------------------------------------- 1 | package me.ag2s.epublib.domain; 2 | 3 | @SuppressWarnings("unused") 4 | public enum ManifestItemProperties implements ManifestProperties { 5 | COVER_IMAGE("cover-image"), 6 | MATHML("mathml"), 7 | NAV("nav"), 8 | REMOTE_RESOURCES("remote-resources"), 9 | SCRIPTED("scripted"), 10 | SVG("svg"), 11 | SWITCH("switch"); 12 | 13 | private final String name; 14 | 15 | ManifestItemProperties(String name) { 16 | this.name = name; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/utils/IntentExtensions.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package io.legado.app.utils 4 | 5 | import android.content.Intent 6 | 7 | fun Intent.putJson(key: String, any: Any?) { 8 | any?.let { 9 | putExtra(key, GSON.toJson(any)) 10 | } 11 | } 12 | 13 | inline fun Intent.getJsonObject(key: String): T? { 14 | val value = getStringExtra(key) 15 | return GSON.fromJsonObject(value).getOrNull() 16 | } 17 | 18 | inline fun Intent.getJsonArray(key: String): List? { 19 | val value = getStringExtra(key) 20 | return GSON.fromJsonArray(value).getOrNull() 21 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cfg_backup.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_photo_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_read_style.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_tab_layout_min.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/menu/backup_restore.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/menu/txt_toc_rule_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 14 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/rhino/VMBridgeReflect.kt: -------------------------------------------------------------------------------- 1 | package com.script.rhino 2 | 3 | import org.mozilla.javascript.VMBridge 4 | 5 | object VMBridgeReflect { 6 | 7 | val instance: VMBridge by lazy { 8 | VMBridge::class.java.getDeclaredField("instance").apply { 9 | isAccessible = true 10 | }.get(null) as VMBridge 11 | } 12 | 13 | val contextLocal: ThreadLocal by lazy { 14 | @Suppress("UNCHECKED_CAST") 15 | instance::class.java.getDeclaredField("contextLocal").apply { 16 | isAccessible = true 17 | }.get(null) as ThreadLocal 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/dao/RssReadRecordDao.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.dao 2 | 3 | import androidx.room.* 4 | import io.legado.app.data.entities.RssReadRecord 5 | 6 | @Dao 7 | interface RssReadRecordDao { 8 | 9 | @Insert(onConflict = OnConflictStrategy.IGNORE) 10 | fun insertRecord(vararg rssReadRecord: RssReadRecord) 11 | 12 | @Query("select * from rssReadRecords order by readTime desc") 13 | fun getRecords(): List 14 | 15 | @get:Query("select count(1) from rssReadRecords") 16 | val countRecords: Int 17 | 18 | @Query("delete from rssReadRecords") 19 | fun deleteAllRecord() 20 | 21 | } -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/data/entities/SearchKeyword.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.data.entities 2 | 3 | import android.os.Parcelable 4 | import androidx.room.Entity 5 | import androidx.room.Index 6 | import androidx.room.PrimaryKey 7 | import kotlinx.parcelize.Parcelize 8 | 9 | 10 | @Parcelize 11 | @Entity(tableName = "search_keywords", indices = [(Index(value = ["word"], unique = true))]) 12 | data class SearchKeyword( 13 | /** 搜索关键词 */ 14 | @PrimaryKey 15 | var word: String = "", 16 | /** 使用次数 */ 17 | var usage: Int = 1, 18 | /** 最后一次使用时间 */ 19 | var lastUseTime: Long = System.currentTimeMillis() 20 | ) : Parcelable 21 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/main/explore/ExploreDiffItemCallBack.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.main.explore 2 | 3 | import androidx.recyclerview.widget.DiffUtil 4 | import io.legado.app.data.entities.BookSourcePart 5 | 6 | 7 | class ExploreDiffItemCallBack : DiffUtil.ItemCallback() { 8 | 9 | override fun areItemsTheSame(oldItem: BookSourcePart, newItem: BookSourcePart): Boolean { 10 | return oldItem == newItem 11 | } 12 | 13 | override fun areContentsTheSame(oldItem: BookSourcePart, newItem: BookSourcePart): Boolean { 14 | return oldItem.bookSourceName == newItem.bookSourceName 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_rss_articles.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/help/update/AppUpdate.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.help.update 2 | 3 | import io.legado.app.help.coroutine.Coroutine 4 | import kotlinx.coroutines.CoroutineScope 5 | 6 | object AppUpdate { 7 | 8 | val gitHubUpdate: AppUpdateInterface? by lazy { 9 | AppUpdateGitHub 10 | } 11 | 12 | data class UpdateInfo( 13 | val tagName: String, 14 | val updateLog: String, 15 | val downloadUrl: String, 16 | val fileName: String 17 | ) 18 | 19 | interface AppUpdateInterface { 20 | 21 | fun check(scope: CoroutineScope): Coroutine 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/lib/mobi/entities/MobiHeader.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.lib.mobi.entities 2 | 3 | data class MobiHeader( 4 | val identifier: String, 5 | val length: Int, 6 | val type: Int, 7 | val encoding: Int, 8 | val uid: Int, 9 | val version: Int, 10 | val titleOffset: Int, 11 | val titleLength: Int, 12 | val localeRegion: Int, 13 | val localeLanguage: Int, 14 | val resourceStart: Int, 15 | val huffcdic: Int, 16 | val numHuffcdic: Int, 17 | val exthFlag: Int, 18 | val trailingFlags: Int, 19 | val indx: Int, 20 | val title: String, 21 | val languege: String 22 | ) 23 | -------------------------------------------------------------------------------- /app/src/main/java/io/legado/app/ui/book/manga/recyclerview/MangaLayoutManager.kt: -------------------------------------------------------------------------------- 1 | package io.legado.app.ui.book.manga.recyclerview 2 | 3 | import android.content.Context 4 | import androidx.recyclerview.widget.LinearLayoutManager 5 | import androidx.recyclerview.widget.RecyclerView 6 | 7 | class MangaLayoutManager(context: Context) : 8 | LinearLayoutManager(context) { 9 | 10 | private val extraLayoutSpace = context.resources.displayMetrics.heightPixels * 3 / 4 11 | 12 | @Deprecated("Deprecated in Java") 13 | override fun getExtraLayoutSpace(state: RecyclerView.State?): Int { 14 | return extraLayoutSpace 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_person_e.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /modules/rhino/src/main/java/com/script/rhino/CollectionExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.script.rhino 2 | 3 | inline fun List.fastBinarySearch( 4 | comparison: (T) -> Int 5 | ): Int { 6 | var low = 0 7 | var high = lastIndex 8 | 9 | while (low <= high) { 10 | val mid = (low + high).ushr(1) // safe from overflows 11 | val midVal = get(mid) 12 | val cmp = comparison(midVal) 13 | 14 | if (cmp < 0) 15 | low = mid + 1 16 | else if (cmp > 0) 17 | high = mid - 1 18 | else 19 | return mid // key found 20 | } 21 | return -(low + 1) // key not found 22 | } 23 | -------------------------------------------------------------------------------- /modules/web/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from '@/router' 4 | import store from '@/store' 5 | import 'element-plus/theme-chalk/dark/css-vars.css' 6 | 7 | createApp(App).use(store).use(router).mount('#app') 8 | // 书架 同步Element PLUS 夜间模式 9 | watch( 10 | () => useBookStore().isNight, 11 | isNight => { 12 | if (isNight) { 13 | document.documentElement.classList.add('dark') 14 | } else { 15 | document.documentElement.classList.remove('dark') 16 | } 17 | }, 18 | ) 19 | 20 | window.addEventListener('vite:preloadError', event => { 21 | event.preventDefault() 22 | }) 23 | --------------------------------------------------------------------------------