├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── custom.md │ └── feature_request.yml ├── PULL_REQUEST_TEMPLATE │ ├── bug_fix.md │ ├── feature_addition.md │ └── submit_h_keyframe.md ├── dependabot.yml └── workflows │ ├── ci.yml │ └── pr_check.yml ├── .gitignore ├── HanimeAnnouncementManagerWebUI ├── HanimeAnnouncementManager.html └── PermitAdmin.py ├── LICENSE ├── README.md ├── README_TECH.md ├── app ├── .gitignore ├── build.gradle.kts ├── keystore │ └── Han1meViewerKeystore.jks ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── yenaly │ │ └── han1meviewer │ │ └── ExampleInstrumentedTest.kt │ ├── debug │ └── res │ │ └── values │ │ └── strings.xml │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── h_keyframes │ │ │ ├── 12444.json │ │ │ ├── 14463.json │ │ │ ├── 21806.json │ │ │ ├── 22068.json │ │ │ ├── 37176.json │ │ │ ├── 37177.json │ │ │ ├── 37178.json │ │ │ ├── 37179.json │ │ │ ├── 37220.json │ │ │ ├── 37221.json │ │ │ ├── 38387.json │ │ │ ├── 38389.json │ │ │ ├── 38457.json │ │ │ ├── 38461.json │ │ │ ├── 39192.json │ │ │ ├── 39305.json │ │ │ ├── 39306.json │ │ │ ├── 39468.json │ │ │ ├── 39811.json │ │ │ ├── 84717.json │ │ │ ├── 84718.json │ │ │ ├── 85926.json │ │ │ ├── 85927.json │ │ │ ├── 87968.json │ │ │ ├── 87969.json │ │ │ ├── 89087.json │ │ │ ├── 89088.json │ │ │ └── README.md │ │ ├── report_reason.json │ │ ├── search_options │ │ │ ├── brands.json │ │ │ ├── duration.json │ │ │ ├── genre.json │ │ │ ├── release_date.json │ │ │ ├── sort_option.json │ │ │ └── tags.json │ │ └── shaders │ │ │ ├── Anime4K_AutoDownscalePre_x2.glsl │ │ │ ├── Anime4K_AutoDownscalePre_x4.glsl │ │ │ ├── Anime4K_Clamp_Highlights.glsl │ │ │ ├── Anime4K_Restore_CNN_M.glsl │ │ │ ├── Anime4K_Restore_CNN_S.glsl │ │ │ ├── Anime4K_Restore_CNN_VL.glsl │ │ │ ├── Anime4K_Upscale_CNN_x2_M.glsl │ │ │ ├── Anime4K_Upscale_CNN_x2_S.glsl │ │ │ └── Anime4K_Upscale_CNN_x2_VL.glsl │ ├── java │ │ └── com │ │ │ └── yenaly │ │ │ └── han1meviewer │ │ │ ├── Constants.kt │ │ │ ├── FirebaseConstants.kt │ │ │ ├── HAdvancedSearch.kt │ │ │ ├── HCacheManager.kt │ │ │ ├── HCrashHandler.kt │ │ │ ├── HFileManager.kt │ │ │ ├── HInitializer.kt │ │ │ ├── HanimeApplication.kt │ │ │ ├── HanimeManager.kt │ │ │ ├── HanimeResolution.kt │ │ │ ├── Preferences.kt │ │ │ ├── VideoCoverSize.kt │ │ │ ├── logic │ │ │ ├── DatabaseRepo.kt │ │ │ ├── NetworkRepo.kt │ │ │ ├── Parser.kt │ │ │ ├── dao │ │ │ │ ├── CheckInRecordDao.kt │ │ │ │ ├── CheckInRecordDatabase.kt │ │ │ │ ├── DownloadDatabase.kt │ │ │ │ ├── HKeyframeDao.kt │ │ │ │ ├── HistoryDatabase.kt │ │ │ │ ├── MiscellanyDatabase.kt │ │ │ │ ├── SearchHistoryDao.kt │ │ │ │ ├── WatchHistoryDao.kt │ │ │ │ └── download │ │ │ │ │ ├── DownloadCategoryDao.kt │ │ │ │ │ └── HanimeDownloadDao.kt │ │ │ ├── entity │ │ │ │ ├── CheckInRecordEntity.kt │ │ │ │ ├── HKeyframeEntity.kt │ │ │ │ ├── SearchHistoryEntity.kt │ │ │ │ ├── WatchHistoryEntity.kt │ │ │ │ └── download │ │ │ │ │ ├── DownloadCategoryEntity.kt │ │ │ │ │ ├── HanimeCategoryCrossRef.kt │ │ │ │ │ ├── HanimeDownloadEntity.kt │ │ │ │ │ └── VideoWithCategories.kt │ │ │ ├── exception │ │ │ │ ├── CloudFlareBlockedException.kt │ │ │ │ ├── HanimeNotFoundException.kt │ │ │ │ ├── IPBlockedException.kt │ │ │ │ └── ParseException.kt │ │ │ ├── model │ │ │ │ ├── Announcement.kt │ │ │ │ ├── HanimeInfo.kt │ │ │ │ ├── HanimePreview.kt │ │ │ │ ├── HanimeVideo.kt │ │ │ │ ├── HomePage.kt │ │ │ │ ├── MultiItemEntity.kt │ │ │ │ ├── MyListItems.kt │ │ │ │ ├── MySubscriptions.kt │ │ │ │ ├── ParamEnum.kt │ │ │ │ ├── Playlists.kt │ │ │ │ ├── ReportReason.kt │ │ │ │ ├── SearchOption.kt │ │ │ │ ├── SearchTag.kt │ │ │ │ ├── VideoComments.kt │ │ │ │ ├── VideoItemType.kt │ │ │ │ └── github │ │ │ │ │ ├── Commit.kt │ │ │ │ │ ├── Latest.kt │ │ │ │ │ ├── Release.kt │ │ │ │ │ └── Workflow.kt │ │ │ ├── network │ │ │ │ ├── GitHubDns.kt │ │ │ │ ├── HCookieJar.kt │ │ │ │ ├── HDns.kt │ │ │ │ ├── HProxySelector.kt │ │ │ │ ├── HUpdater.kt │ │ │ │ ├── HanimeNetwork.kt │ │ │ │ ├── ServiceCreator.kt │ │ │ │ ├── interceptor │ │ │ │ │ ├── CloudflareInterceptor.kt │ │ │ │ │ ├── SpeedLimitInterceptor.kt │ │ │ │ │ ├── SpeedLimitResponseBody.kt │ │ │ │ │ ├── UrlLoggingInterceptor.kt │ │ │ │ │ └── UserAgentInterceptor.kt │ │ │ │ └── service │ │ │ │ │ ├── HGitHubService.kt │ │ │ │ │ ├── HanimeBaseService.kt │ │ │ │ │ ├── HanimeCommentService.kt │ │ │ │ │ ├── HanimeMyListService.kt │ │ │ │ │ └── HanimeSubscriptionService.kt │ │ │ └── state │ │ │ │ ├── DownloadState.kt │ │ │ │ ├── PageLoadingState.kt │ │ │ │ ├── VideoLoadingState.kt │ │ │ │ └── WebsiteState.kt │ │ │ ├── ui │ │ │ ├── StateLayoutMixin.kt │ │ │ ├── activity │ │ │ │ ├── CloudflareActivity.kt │ │ │ │ ├── LoginActivity.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── QRcodeScannerActivity.kt │ │ │ │ ├── SettingsActivity.kt │ │ │ │ └── SettingsRouter.kt │ │ │ ├── adapter │ │ │ │ ├── AdapterLikeDataBindingPage.kt │ │ │ │ ├── AnnouncementAdapter.kt │ │ │ │ ├── AnnouncementCardAdapter.kt │ │ │ │ ├── BaseSingleDifferAdapter.kt │ │ │ │ ├── DelayAdapter.kt │ │ │ │ ├── FixedGridLayoutManager.kt │ │ │ │ ├── HKeyframesRvAdapter.kt │ │ │ │ ├── HSearchTagAdapter.kt │ │ │ │ ├── HanimeAdvancedSearchHistoryAdapter.kt │ │ │ │ ├── HanimeDownloadedRvAdapter.kt │ │ │ │ ├── HanimeDownloadingRvAdapter.kt │ │ │ │ ├── HanimeMyListVideoAdapter.kt │ │ │ │ ├── HanimePreviewNewsRvAdapter.kt │ │ │ │ ├── HanimePreviewTourRvAdapter.kt │ │ │ │ ├── HanimeSearchHistoryRvAdapter.kt │ │ │ │ ├── HanimeVideoRvAdapter.kt │ │ │ │ ├── PlaylistRvAdapter.kt │ │ │ │ ├── ReleaseDateAdapter.kt │ │ │ │ ├── RvWrapper.kt │ │ │ │ ├── SharedHKeyframesRvAdapter.kt │ │ │ │ ├── SuperResolutionAdapter.kt │ │ │ │ ├── VideoColumnTitleAdapter.kt │ │ │ │ ├── VideoCommentRvAdapter.kt │ │ │ │ ├── VideoSpeedAdapter.kt │ │ │ │ └── WatchHistoryRvAdapter.kt │ │ │ ├── fragment │ │ │ │ ├── ComposeItem.kt │ │ │ │ ├── ComposePreview.kt │ │ │ │ ├── ComposePreviewDataSource.kt │ │ │ │ ├── ComposeUtils.kt │ │ │ │ ├── IToolbarFragment.kt │ │ │ │ ├── LoginNeededFragmentMixin.kt │ │ │ │ ├── PermissionRequester.kt │ │ │ │ ├── PlaylistBottomSheetDialogFragment.kt │ │ │ │ ├── ToolbarHost.kt │ │ │ │ ├── dailycheckin │ │ │ │ │ └── DailyCheckInFragment.kt │ │ │ │ ├── funny │ │ │ │ │ ├── FunnyTouchListener.kt │ │ │ │ │ └── SomeFunny.kt │ │ │ │ ├── home │ │ │ │ │ ├── DownloadFragment.kt │ │ │ │ │ ├── HomePageFragment.kt │ │ │ │ │ ├── MyFavVideoFragment.kt │ │ │ │ │ ├── MyPlayListFragmentV2.kt │ │ │ │ │ ├── MyPlaylistFragment.kt │ │ │ │ │ ├── MyWatchLaterFragment.kt │ │ │ │ │ ├── SubscriptionFragment.kt │ │ │ │ │ ├── WatchHistoryFragment.kt │ │ │ │ │ ├── download │ │ │ │ │ │ ├── DownloadedFragment.kt │ │ │ │ │ │ └── DownloadingFragment.kt │ │ │ │ │ ├── myplaylist │ │ │ │ │ │ ├── MyPlayListScreen.kt │ │ │ │ │ │ └── MyplayListBottomSheet.kt │ │ │ │ │ ├── preview │ │ │ │ │ │ ├── PreviewCommentFragment.kt │ │ │ │ │ │ └── PreviewFragment.kt │ │ │ │ │ └── subscription │ │ │ │ │ │ └── SubscriptionScreen.kt │ │ │ │ ├── search │ │ │ │ │ ├── HCheckBoxFragment.kt │ │ │ │ │ ├── HMultiChoicesDialog.kt │ │ │ │ │ ├── SearchFragment.kt │ │ │ │ │ └── SearchOptionsPopupFragment.kt │ │ │ │ ├── settings │ │ │ │ │ ├── DownloadSettingsFragment.kt │ │ │ │ │ ├── HKeyframeSettingsFragment.kt │ │ │ │ │ ├── HKeyframesFragment.kt │ │ │ │ │ ├── HomeSettingsFragment.kt │ │ │ │ │ ├── MpvPlayerSettings.kt │ │ │ │ │ ├── NetworkSettingsFragment.kt │ │ │ │ │ ├── PlayerSettingsFragment.kt │ │ │ │ │ └── SharedHKeyframesFragment.kt │ │ │ │ └── video │ │ │ │ │ ├── ChildCommentPopupFragment.kt │ │ │ │ │ ├── CommentFragment.kt │ │ │ │ │ ├── VideoFragment.kt │ │ │ │ │ └── VideoIntroductionFragment.kt │ │ │ ├── popup │ │ │ │ ├── CoilImageLoader.kt │ │ │ │ ├── HTimePickerPopup.kt │ │ │ │ └── ReplyPopup.kt │ │ │ ├── theme │ │ │ │ ├── Color.kt │ │ │ │ └── Theme.kt │ │ │ ├── view │ │ │ │ ├── BlurTransformation.kt │ │ │ │ ├── CenterLinearLayoutManager.kt │ │ │ │ ├── CollapsibleTags.kt │ │ │ │ ├── HOptionChip.kt │ │ │ │ ├── HanimeSearchBar.kt │ │ │ │ ├── HorizontalNestedScrollView.kt │ │ │ │ ├── LinearSmoothToStartScroller.kt │ │ │ │ ├── PlaylistHeader.kt │ │ │ │ ├── funcbar │ │ │ │ │ ├── Hanidapter.kt │ │ │ │ │ ├── Hanidock.kt │ │ │ │ │ ├── Hanidokitem.kt │ │ │ │ │ └── Hanidontroller.kt │ │ │ │ ├── pref │ │ │ │ │ ├── HPrivacyPreference.kt │ │ │ │ │ ├── MaterialDialogPreference.kt │ │ │ │ │ └── MaterialSliderPreference.kt │ │ │ │ └── video │ │ │ │ │ ├── HJzvdStd.kt │ │ │ │ │ ├── HMediaKernel.kt │ │ │ │ │ ├── HanimeDataSource.kt │ │ │ │ │ └── VideoPlayerAppBarBehavior.kt │ │ │ └── viewmodel │ │ │ │ ├── AppViewModel.kt │ │ │ │ ├── CheckInCalendarViewModel.kt │ │ │ │ ├── CommentViewModel.kt │ │ │ │ ├── DownloadViewModel.kt │ │ │ │ ├── IHCsrfToken.kt │ │ │ │ ├── MainViewModel.kt │ │ │ │ ├── MyListViewModel.kt │ │ │ │ ├── MyPlayListViewModelV2.kt │ │ │ │ ├── MySubscriptionsViewModel.kt │ │ │ │ ├── PreviewCommentPrefetcher.kt │ │ │ │ ├── PreviewViewModel.kt │ │ │ │ ├── SearchViewModel.kt │ │ │ │ ├── SettingsViewModel.kt │ │ │ │ ├── VideoViewModel.kt │ │ │ │ └── mylist │ │ │ │ ├── FavSubViewModel.kt │ │ │ │ ├── PlaylistSubViewModel.kt │ │ │ │ └── WatchLaterSubViewModel.kt │ │ │ ├── util │ │ │ ├── Adapters.kt │ │ │ ├── AlertDialogs.kt │ │ │ ├── Animations.kt │ │ │ ├── AnimeShaders.kt │ │ │ ├── Colors.kt │ │ │ ├── CommentUtils.kt │ │ │ ├── Common.kt │ │ │ ├── Cookies.kt │ │ │ ├── Files.kt │ │ │ ├── Firebases.kt │ │ │ ├── HImageMeower.kt │ │ │ ├── Networks.kt │ │ │ ├── Parcels.kt │ │ │ ├── Permissions.kt │ │ │ ├── Preferences.kt │ │ │ ├── SafFileManager.kt │ │ │ ├── TextViews.kt │ │ │ ├── ThemeUtils.kt │ │ │ ├── Versions.kt │ │ │ └── Views.kt │ │ │ └── worker │ │ │ ├── HUpdateWorker.kt │ │ │ ├── HanimeDownloadManager.kt │ │ │ ├── HanimeDownloadManagerV2.kt │ │ │ ├── HanimeDownloadWorker.kt │ │ │ └── WorkerMixin.kt │ └── res │ │ ├── anim │ │ ├── fade_in.xml │ │ ├── fade_out.xml │ │ ├── slide_in_left.xml │ │ ├── slide_in_right.xml │ │ ├── slide_out_left.xml │ │ └── slide_out_right.xml │ │ ├── color │ │ ├── nav_item_icon_color.xml │ │ └── nav_item_text_color.xml │ │ ├── drawable │ │ ├── akarin.png │ │ ├── apply_deep_links.png │ │ ├── baseline_add_24.xml │ │ ├── baseline_add_link_24.xml │ │ ├── baseline_advanced_search_24.xml │ │ ├── baseline_arrow_forward_ios_24.xml │ │ ├── baseline_atomic_24.xml │ │ ├── baseline_bug_report_24.xml │ │ ├── baseline_cache_24.xml │ │ ├── baseline_cert_24.xml │ │ ├── baseline_chip_24.xml │ │ ├── baseline_count_24.xml │ │ ├── baseline_count_down_24.xml │ │ ├── baseline_custom_24.xml │ │ ├── baseline_data_usage_24.xml │ │ ├── baseline_deband_24.xml │ │ ├── baseline_decoder_24.xml │ │ ├── baseline_delay_24.xml │ │ ├── baseline_domain_24.xml │ │ ├── baseline_edit_24.xml │ │ ├── baseline_error_outline_24.xml │ │ ├── baseline_export_24.xml │ │ ├── baseline_format_list_bulleted_24.xml │ │ ├── baseline_forum_24.xml │ │ ├── baseline_frame_inter_24.xml │ │ ├── baseline_frame_jump_24.xml │ │ ├── baseline_h_24.xml │ │ ├── baseline_hosts_24.xml │ │ ├── baseline_keyboard_arrow_down_24.xml │ │ ├── baseline_keyboard_arrow_up_24.xml │ │ ├── baseline_manage_24.xml │ │ ├── baseline_more_horiz_24.xml │ │ ├── baseline_online_manage_24.xml │ │ ├── baseline_overtime_24.xml │ │ ├── baseline_path_24.xml │ │ ├── baseline_player_24.xml │ │ ├── baseline_prohibit_24.xml │ │ ├── baseline_refresh_24.xml │ │ ├── baseline_remove_circle_24.xml │ │ ├── baseline_render_24.xml │ │ ├── baseline_seek_24.xml │ │ ├── baseline_share_24.xml │ │ ├── baseline_share_first_24.xml │ │ ├── baseline_simp_to_trad_24.xml │ │ ├── baseline_sort_24.xml │ │ ├── baseline_speed2_24.xml │ │ ├── baseline_speed_24.xml │ │ ├── baseline_touch_24.xml │ │ ├── baseline_vpn_24.xml │ │ ├── bg_default_header.png │ │ ├── cookies_intro1.png │ │ ├── frosted_glass.xml │ │ ├── gradient_black_transparent_90.xml │ │ ├── ic_baseline_4k_24.xml │ │ ├── ic_baseline_access_time_24.xml │ │ ├── ic_baseline_alert_24.xml │ │ ├── ic_baseline_arrow_back_24.xml │ │ ├── ic_baseline_arrow_forward_24.xml │ │ ├── ic_baseline_book.xml │ │ ├── ic_baseline_cancel_24.xml │ │ ├── ic_baseline_check_circle_24.xml │ │ ├── ic_baseline_clear_all_24.xml │ │ ├── ic_baseline_close_24.xml │ │ ├── ic_baseline_comment_24.xml │ │ ├── ic_baseline_delete_24.xml │ │ ├── ic_baseline_disable_24.xml │ │ ├── ic_baseline_download_24.xml │ │ ├── ic_baseline_favorite_24.xml │ │ ├── ic_baseline_favorite_border_24.xml │ │ ├── ic_baseline_help_24.xml │ │ ├── ic_baseline_history_24.xml │ │ ├── ic_baseline_home_24.xml │ │ ├── ic_baseline_info_24.xml │ │ ├── ic_baseline_language_24.xml │ │ ├── ic_baseline_list_24.xml │ │ ├── ic_baseline_mask.xml │ │ ├── ic_baseline_moon_24.xml │ │ ├── ic_baseline_more_time_24.xml │ │ ├── ic_baseline_newspaper_24.xml │ │ ├── ic_baseline_pantsu.xml │ │ ├── ic_baseline_pause_24.xml │ │ ├── ic_baseline_pause_24_tintwhite.xml │ │ ├── ic_baseline_play_arrow_24.xml │ │ ├── ic_baseline_play_arrow_24_tintwhite.xml │ │ ├── ic_baseline_play_circle_outline_24.xml │ │ ├── ic_baseline_reply_24.xml │ │ ├── ic_baseline_report_24.xml │ │ ├── ic_baseline_scan_24.xml │ │ ├── ic_baseline_search_24.xml │ │ ├── ic_baseline_send_24.xml │ │ ├── ic_baseline_settings_24.xml │ │ ├── ic_baseline_share_24.xml │ │ ├── ic_baseline_skip_24.xml │ │ ├── ic_baseline_speed_24.xml │ │ ├── ic_baseline_theme_24.xml │ │ ├── ic_baseline_thumb_down_alt_24.xml │ │ ├── ic_baseline_thumb_down_off_alt_24.xml │ │ ├── ic_baseline_thumb_up_alt_24.xml │ │ ├── ic_baseline_thumb_up_off_alt_24.xml │ │ ├── ic_baseline_update_24.xml │ │ ├── ic_baseline_watch_later_24.xml │ │ ├── ic_clock.xml │ │ ├── ic_comments.xml │ │ ├── ic_ext_link.xml │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_calc.webp │ │ ├── ic_launcher_cornhub.webp │ │ ├── ic_launcher_debug_background.xml │ │ ├── ic_launcher_xxt.webp │ │ ├── ic_oss.xml │ │ ├── ic_pip_mode.xml │ │ ├── ic_send_selector.xml │ │ ├── ic_setting_applock.xml │ │ ├── ic_setting_ci.xml │ │ ├── ic_setting_lang.xml │ │ ├── ic_subscribtion.xml │ │ ├── ic_video_quilty.xml │ │ ├── icon_circle_bg.xml │ │ ├── indicator_active.xml │ │ ├── indicator_inactive.xml │ │ ├── linear_gradient_90.xml │ │ ├── linear_gradient_90_notrans.xml │ │ ├── neuro_sad.png │ │ ├── outline_home_24.xml │ │ ├── scaled_added_time.xml │ │ ├── search_bar_background.xml │ │ ├── shape_download_func_bar.xml │ │ ├── shape_preview_button_left.xml │ │ ├── shape_preview_button_right.xml │ │ └── shape_title_mask.xml │ │ ├── layout │ │ ├── activity_cloudflare.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_settings.xml │ │ ├── activity_video.xml │ │ ├── base_column_title.xml │ │ ├── delay_test_dialog.xml │ │ ├── dialog_announcement.xml │ │ ├── dialog_apply_deep_links.xml │ │ ├── dialog_login.xml │ │ ├── dialog_modify_h_keyframe.xml │ │ ├── dialog_modify_h_keyframes.xml │ │ ├── dialog_playlist_modify_edit_text.xml │ │ ├── dialog_proxy.xml │ │ ├── fragment_bottom_sheet_list.xml │ │ ├── fragment_comment.xml │ │ ├── fragment_download.xml │ │ ├── fragment_h_keyframes.xml │ │ ├── fragment_home_page.xml │ │ ├── fragment_list_only.xml │ │ ├── fragment_page_list.xml │ │ ├── fragment_playlist.xml │ │ ├── fragment_preview.xml │ │ ├── fragment_preview_comment.xml │ │ ├── fragment_search.xml │ │ ├── fragment_video.xml │ │ ├── fragment_video_introduction.xml │ │ ├── item_announcement.xml │ │ ├── item_announcement_card.xml │ │ ├── item_delay_result.xml │ │ ├── item_h_keyframe.xml │ │ ├── item_h_keyframes.xml │ │ ├── item_hanidock.xml │ │ ├── item_hanime_advanced_search_history.xml │ │ ├── item_hanime_downloaded.xml │ │ ├── item_hanime_downloading.xml │ │ ├── item_hanime_preview_news_pic.xml │ │ ├── item_hanime_preview_news_v2.xml │ │ ├── item_hanime_video.xml │ │ ├── item_hanime_video_simplified.xml │ │ ├── item_playlist.xml │ │ ├── item_preview_tour_simplified.xml │ │ ├── item_rv_wrapper.xml │ │ ├── item_search_history.xml │ │ ├── item_shared_h_keyframes.xml │ │ ├── item_simple_card.xml │ │ ├── item_simple_icon_with_text.xml │ │ ├── item_video_column_title.xml │ │ ├── item_video_comment.xml │ │ ├── item_video_introduction.xml │ │ ├── item_video_tag_chip.xml │ │ ├── item_watch_history.xml │ │ ├── jz_layout_speed.xml │ │ ├── layout_collapsible_tag.xml │ │ ├── layout_dialog_progress.xml │ │ ├── layout_empty_view.xml │ │ ├── layout_hanidock.xml │ │ ├── layout_hanime_search_bar.xml │ │ ├── layout_header_h_keyframes.xml │ │ ├── layout_jzvd_with_speed.xml │ │ ├── layout_playlist_header_v2.xml │ │ ├── layout_rv_scrollbars.xml │ │ ├── nav_header_ability.xml │ │ ├── pop_up_ext_h_time_picker.xml │ │ ├── pop_up_fragment_child_comment.xml │ │ ├── pop_up_fragment_search_options.xml │ │ ├── pop_up_hanime_search_tag.xml │ │ ├── pop_up_reply.xml │ │ └── pref_material_slider.xml │ │ ├── menu │ │ ├── menu_comment_sort.xml │ │ ├── menu_downloaded_toolbar.xml │ │ ├── menu_downloading_toolbar.xml │ │ ├── menu_main_nv.xml │ │ ├── menu_main_toolbar.xml │ │ ├── menu_my_list_toolbar.xml │ │ ├── menu_playlist_toolbar.xml │ │ ├── menu_preview_toolbar.xml │ │ └── menu_watch_history_toolbar.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ ├── ic_launcher_calc.xml │ │ ├── ic_launcher_calc_round.xml │ │ ├── ic_launcher_cornhub.xml │ │ ├── ic_launcher_cornhub_round.xml │ │ ├── ic_launcher_debug.xml │ │ ├── ic_launcher_debug_round.xml │ │ ├── ic_launcher_round.xml │ │ ├── ic_launcher_xxt.xml │ │ └── ic_launcher_xxt_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_calc.webp │ │ ├── ic_launcher_calc_foreground.webp │ │ ├── ic_launcher_cornhub.webp │ │ ├── ic_launcher_cornhub_foreground.webp │ │ ├── ic_launcher_debug.webp │ │ ├── ic_launcher_debug_foreground.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_round.webp │ │ ├── ic_launcher_xxt.webp │ │ ├── ic_launcher_xxt_background.webp │ │ └── ic_launcher_xxt_foreground.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_calc.webp │ │ ├── ic_launcher_calc_foreground.webp │ │ ├── ic_launcher_cornhub.webp │ │ ├── ic_launcher_cornhub_foreground.webp │ │ ├── ic_launcher_debug.webp │ │ ├── ic_launcher_debug_foreground.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_round.webp │ │ ├── ic_launcher_xxt.webp │ │ ├── ic_launcher_xxt_background.webp │ │ └── ic_launcher_xxt_foreground.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_calc.webp │ │ ├── ic_launcher_calc_foreground.webp │ │ ├── ic_launcher_cornhub.webp │ │ ├── ic_launcher_cornhub_foreground.webp │ │ ├── ic_launcher_debug.webp │ │ ├── ic_launcher_debug_foreground.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_round.webp │ │ ├── ic_launcher_xxt.webp │ │ ├── ic_launcher_xxt_background.webp │ │ └── ic_launcher_xxt_foreground.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_calc.webp │ │ ├── ic_launcher_calc_foreground.webp │ │ ├── ic_launcher_calc_round.webp │ │ ├── ic_launcher_cornhub.webp │ │ ├── ic_launcher_cornhub_foreground.webp │ │ ├── ic_launcher_cornhub_round.webp │ │ ├── ic_launcher_debug.webp │ │ ├── ic_launcher_debug_foreground.webp │ │ ├── ic_launcher_debug_round.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_round.webp │ │ ├── ic_launcher_xxt.webp │ │ ├── ic_launcher_xxt_background.webp │ │ ├── ic_launcher_xxt_foreground.webp │ │ └── ic_launcher_xxt_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_calc.webp │ │ ├── ic_launcher_calc_foreground.webp │ │ ├── ic_launcher_calc_round.webp │ │ ├── ic_launcher_cornhub.webp │ │ ├── ic_launcher_cornhub_foreground.webp │ │ ├── ic_launcher_cornhub_round.webp │ │ ├── ic_launcher_debug.webp │ │ ├── ic_launcher_debug_foreground.webp │ │ ├── ic_launcher_debug_round.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_round.webp │ │ ├── ic_launcher_xxt.webp │ │ ├── ic_launcher_xxt_background.webp │ │ ├── ic_launcher_xxt_foreground.webp │ │ └── ic_launcher_xxt_round.webp │ │ ├── navigation │ │ ├── nav_main.xml │ │ └── nav_settings.xml │ │ ├── raw │ │ └── akarin.png │ │ ├── values-en │ │ └── strings.xml │ │ ├── values-ja │ │ └── strings.xml │ │ ├── values-land │ │ └── dimens.xml │ │ ├── values-night │ │ └── colors.xml │ │ ├── values-zh-rCN │ │ └── strings.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── bools.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_calc_background.xml │ │ ├── ic_launcher_cornhub_background.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ ├── data_extraction_rules.xml │ │ ├── file_paths.xml │ │ ├── setting_mpv_player.xml │ │ ├── settings_download.xml │ │ ├── settings_h_keyframe.xml │ │ ├── settings_home.xml │ │ ├── settings_network.xml │ │ └── settings_player.xml │ └── test │ └── java │ └── com │ └── yenaly │ └── han1meviewer │ └── ExampleUnitTest.kt ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts └── src │ └── main │ └── java │ └── Config.kt ├── develop ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── icon ├── icon_han1me_viewer-rurires.png ├── icon_han1me_viewer-rurires.svg └── icon_transparent_han1me_viewer-rurires.png ├── readme_01.png ├── readme_02.png ├── readme_03.png ├── readme_04.png ├── readme_05.png ├── readme_06.png ├── readme_07.png ├── settings.gradle.kts └── yenaly_libs ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── yenaly │ └── yenaly_libs │ └── ExampleInstrumentedTest.kt ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── yenaly │ │ └── yenaly_libs │ │ ├── ActivityManager.kt │ │ ├── SingletonHolder.kt │ │ ├── base │ │ ├── IViewBinding.kt │ │ ├── YenalyActivity.kt │ │ ├── YenalyApplication.kt │ │ ├── YenalyBottomSheetDialogFragment.kt │ │ ├── YenalyCrashHandler.kt │ │ ├── YenalyFragment.kt │ │ ├── YenalyInitializer.kt │ │ ├── YenalyViewModel.kt │ │ ├── dialog │ │ │ └── YenalyCrashDialogActivity.kt │ │ ├── frame │ │ │ ├── FrameActivity.kt │ │ │ └── FrameFragment.kt │ │ ├── preference │ │ │ ├── LongClickablePreference.kt │ │ │ ├── LongClickableSwitchPreference.kt │ │ │ └── MaterialSwitchPreference.kt │ │ ├── settings │ │ │ ├── YenalySettingsActivity.kt │ │ │ └── YenalySettingsFragment.kt │ │ └── view │ │ │ ├── NestedScrollableHost.kt │ │ │ └── RecyclerViewAtViewPager2.kt │ │ └── utils │ │ ├── ActivityResultUtil.kt │ │ ├── AppUtil.kt │ │ ├── ArrayUtil.kt │ │ ├── Base64Util.kt │ │ ├── ClipboardUtil.kt │ │ ├── ContextUtil.kt │ │ ├── DeviceUtil.kt │ │ ├── FileUtil.kt │ │ ├── ImageUtil.kt │ │ ├── LanguageHelper.kt │ │ ├── LogUtil.kt │ │ ├── OrientationManager.kt │ │ ├── ResourceUtil.kt │ │ ├── ShareUtil.kt │ │ ├── SharedPreferencesUtil.kt │ │ ├── SingleFlowLaunch.kt │ │ ├── SnackBarUtil.kt │ │ ├── SystemStatusUtil.kt │ │ ├── TextUtil.kt │ │ ├── ToastUtil.kt │ │ ├── UnicodeUtil.kt │ │ ├── UriUtil.kt │ │ ├── _AesUtil.kt │ │ ├── _GsonUtil.kt │ │ ├── _IntentUtil.kt │ │ ├── _LazyUtil.kt │ │ ├── span │ │ ├── SpannedTextGenerator.kt │ │ ├── YenalyImageSpan.kt │ │ └── YenalyQuoteSpan.kt │ │ └── view │ │ ├── AppBarLayoutStateChangeListener.kt │ │ ├── BottomNavViewMediator.kt │ │ ├── BottomNavViewUtil.kt │ │ ├── BottomNavigationViewMediator.kt │ │ ├── ClickUtil.kt │ │ ├── EditTextUtil.kt │ │ ├── SimpleBottomNavViewMediator.kt │ │ ├── SimpleFragmentStateAdapter.kt │ │ ├── TabLayoutUtil.kt │ │ ├── ViewPagerUtil.kt │ │ ├── ViewUtil.kt │ │ └── YenalyHideBottomViewOnScrollBehavior.kt └── res │ ├── layout │ ├── yenaly_activity_crash_dialog.xml │ ├── yenaly_activity_settings.xml │ └── yenaly_preference_switch_widget.xml │ ├── values │ ├── ids.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── http_network_config.xml └── test └── java └── com └── yenaly └── yenaly_libs └── UtilUnitTest.kt /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 自定義問題 3 | about: 描述此問題的目的 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: ⭐ 功能請求 2 | description: 建議一個功能來改善 Han1meViewer 3 | labels: [ good idea | 好主意 ] 4 | body: 5 | 6 | - type: textarea 7 | id: feature-description 8 | attributes: 9 | label: 描述您建議的功能 10 | description: 如何改進 Han1meViewer? 11 | placeholder: | 12 | Example: 13 | "我想要bla bla bla..." 14 | validations: 15 | required: true 16 | 17 | - type: textarea 18 | id: other-details 19 | attributes: 20 | label: 其他你想講的 21 | description: 比如哪些軟體有您所說的類似功能,我方便偷過來 22 | placeholder: | 23 | 其他補充資訊 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/bug_fix.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Bug 修復" 3 | about: "用於提交 Bug 修復的拉取請求" 4 | title: "[BUGFIX] <簡短描述>" 5 | labels: "bug" 6 | assignees: "" 7 | --- 8 | 9 | ### 描述 10 | 11 | 12 | 13 | ### 修復方法 14 | 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/feature_addition.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "新功能添加" 3 | about: "用於提交新功能的拉取請求" 4 | title: "[FEATURE] <簡短描述>" 5 | labels: "good idea | 好主意" 6 | assignees: "" 7 | --- 8 | 9 | ### 功能描述 10 | 11 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/submit_h_keyframe.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "提交關鍵H幀" 3 | about: "分享你的關鍵H幀" 4 | title: "[HKeyframe] <簡短描述>" 5 | labels: "𝐇Keyframe" 6 | assignees: "" 7 | --- 8 | 9 | ### 關鍵H幀描述 10 | 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gradle 4 | directory: "/" # Location of package manifests 5 | schedule: 6 | interval: weekly -------------------------------------------------------------------------------- /.github/workflows/pr_check.yml: -------------------------------------------------------------------------------- 1 | permissions: 2 | contents: read 3 | name: Pull Request Check 4 | 5 | on: 6 | pull_request: 7 | branches: [ "main" ] 8 | paths-ignore: 9 | - "**.md" 10 | 11 | jobs: 12 | check: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | 20 | - name: Set up JDK 21 21 | uses: actions/setup-java@v4 22 | with: 23 | java-version: '21' 24 | distribution: 'temurin' 25 | cache: gradle 26 | 27 | - name: Load Google Services File 28 | env: 29 | DATA: ${{ secrets.GOOGLE_SERVICES_JSON_BASE64 }} 30 | run: echo $DATA | base64 -di > app/google-services.json 31 | 32 | - name: Grant execute permission for gradlew 33 | run: chmod +x gradlew 34 | 35 | - name: Build 36 | run: ./gradlew buildDebug -x lint 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /captures 12 | .externalNativeBuild 13 | .cxx 14 | local.properties 15 | /app/ha1_github_token.txt 16 | /app/release/ 17 | /app/debug/ 18 | # Android Studio 项目文件 19 | /.idea/ 20 | /.gradle/ 21 | /build/ 22 | /captures/ 23 | 24 | # Gradle 缓存 25 | .gradle/ 26 | gradle-app.setting 27 | !gradle-wrapper.jar 28 | 29 | # 构建输出 30 | **/build/ 31 | **/outputs/ 32 | 33 | # 本地配置文件 34 | **/google-services.json 35 | **/app/google-services.json 36 | 37 | # 系统文件 38 | Thumbs.db 39 | 40 | # 日志和临时文件 41 | *.log 42 | *.tmp 43 | *.swp 44 | 45 | # 开发环境文件 46 | .env 47 | .secrets/ 48 | 49 | # Kotlin 相关 50 | .kotlin/ 51 | .kotlin_dependencies 52 | 53 | # 其他忽略项 54 | **/extra/ 55 | **/test-output/ 56 | **/reports/ 57 | **/profiles/ 58 | 59 | # 特定项目忽略 60 | /yenaly_libs/local/ 61 | /icon/temp/ 62 | 63 | # 但保留gradle wrapper 64 | !gradle/wrapper/gradle-wrapper.jar 65 | 66 | # 忽略所有构建输出的 APK 文件 67 | **/build/outputs/apk/ 68 | **/*.apk 69 | 70 | # 忽略 debug 测试构建 71 | /app/build/outputs/apk/debug/ -------------------------------------------------------------------------------- /HanimeAnnouncementManagerWebUI/PermitAdmin.py: -------------------------------------------------------------------------------- 1 | import firebase_admin 2 | from firebase_admin import credentials, auth 3 | 4 | cred = credentials.Certificate("serviceAccountKey.json") 5 | firebase_admin.initialize_app(cred) 6 | 7 | # 需要设置权限的用户 UID 8 | uid = '' 9 | 10 | # 设置自定义声明 11 | auth.set_custom_user_claims(uid, {'isAdmin' :True}) 12 | 13 | print('成功设置管理员权限') 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /keystore/ha1_keystore_password.txt 3 | /ha1_github_token.txt 4 | -------------------------------------------------------------------------------- /app/keystore/Han1meViewerKeystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/keystore/Han1meViewerKeystore.jks -------------------------------------------------------------------------------- /app/src/androidTest/java/com/yenaly/han1meviewer/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.yenaly.han1meviewer", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/debug/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | HANi [Debug] 4 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/12444.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "12444", 3 | "group": "思春期SEX", 4 | "title": "思春期SEX#1", 5 | "episode": 1, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 482500, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 545000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 832000, 18 | "prompt": null 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/14463.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "14463", 3 | "group": "思春期SEX", 4 | "title": "思春期SEX#3", 5 | "episode": 3, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 311500, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 432500, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 824000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 861300, 22 | "prompt": null 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/21806.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "21806", 3 | "group": "思春期SEX", 4 | "title": "思春期SEX#4", 5 | "episode": 4, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 481000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 657700, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 742700, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 813000, 22 | "prompt": null 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/22068.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "22068", 3 | "group": "思春期SEX", 4 | "title": "思春期SEX#2", 5 | "episode": 2, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 324000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 602000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 734000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 816000, 22 | "prompt": null 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/37176.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "37176", 3 | "group": "援助交配", 4 | "title": "援助交配#1", 5 | "episode": 1, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 363600, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 633000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 796000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 881700, 22 | "prompt": null 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/37177.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "37177", 3 | "group": "援助交配", 4 | "title": "援助交配#2", 5 | "episode": 2, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 376000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 420000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 600000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 774000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 800000, 26 | "prompt": null 27 | }, 28 | { 29 | "position": 840000, 30 | "prompt": null 31 | }, 32 | { 33 | "position": 856500, 34 | "prompt": null 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/37178.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "37178", 3 | "group": "援助交配", 4 | "title": "援助交配#3", 5 | "episode": 3, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 239000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 307000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 439000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 641000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 820000, 26 | "prompt": null 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/37179.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "37179", 3 | "group": "援助交配", 4 | "title": "援助交配#4", 5 | "episode": 4, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 36000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 480000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 570000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 655000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 800000, 26 | "prompt": null 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/37220.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "37220", 3 | "group": "今泉家似乎變成辣妹的聚會所", 4 | "title": "今泉家似乎變成辣妹的聚會所#1", 5 | "episode": 1, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 265000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 403000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 493000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 540000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 604000, 26 | "prompt": null 27 | }, 28 | { 29 | "position": 725000, 30 | "prompt": null 31 | }, 32 | { 33 | "position": 769000, 34 | "prompt": null 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/37221.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "videoCode": "37221", 4 | "group": "今泉家似乎變成辣妹的聚會所", 5 | "title": "今泉家似乎變成辣妹的聚會所#2", 6 | "episode": 2, 7 | "author": "NeKoOuO", 8 | "keyframes": [ 9 | { 10 | "position": 278500, 11 | "prompt": null 12 | }, 13 | { 14 | "position": 403000, 15 | "prompt": null 16 | }, 17 | { 18 | "position": 510000, 19 | "prompt": null 20 | }, 21 | { 22 | "position": 627000, 23 | "prompt": null 24 | }, 25 | { 26 | "position": 836000, 27 | "prompt": null 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/38387.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "38387", 3 | "group": "援助交配", 4 | "title": "援助交配#5", 5 | "episode": 5, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 335000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 652000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 817000, 18 | "prompt": null 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/38389.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "38389", 3 | "group": "闇憑村", 4 | "title": "闇憑村#1", 5 | "episode": 1, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 290700, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 428000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 510000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 592000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 798000, 26 | "prompt": null 27 | }, 28 | { 29 | "position": 934500, 30 | "prompt": null 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/38457.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "38457", 3 | "group": "闇憑村", 4 | "title": "闇憑村#2", 5 | "episode": 2, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 345300, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 458000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 502500, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 507500, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 549000, 26 | "prompt": null 27 | }, 28 | { 29 | "position": 562000, 30 | "prompt": null 31 | }, 32 | { 33 | "position": 574000, 34 | "prompt": null 35 | }, 36 | { 37 | "position": 686000, 38 | "prompt": null 39 | }, 40 | { 41 | "position": 779500, 42 | "prompt": null 43 | }, 44 | { 45 | "position": 868000, 46 | "prompt": null 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/38461.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "38461", 3 | "group": "援助交配", 4 | "title": "援助交配#6", 5 | "episode": 6, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 86000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 638000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 755000, 18 | "prompt": null 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/39192.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "39192", 3 | "group": "援助交配", 4 | "title": "援助交配#7", 5 | "episode": 7, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 260000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 413500, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 520000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 564000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 656000, 26 | "prompt": null 27 | }, 28 | { 29 | "position": 802000, 30 | "prompt": null 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/39305.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "39305", 3 | "group": "到了異世界就拿出性本事", 4 | "title": "到了異世界就拿出性本事#1", 5 | "episode": 1, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 387500, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 457000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 712500, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 829500, 22 | "prompt": null 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/39306.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "39306", 3 | "group": "到了異世界就拿出性本事", 4 | "title": "到了異世界就拿出性本事#2", 5 | "episode": 2, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 254000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 405000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 502000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 740500, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 914000, 26 | "prompt": null 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/39468.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "39468", 3 | "group": "援助交配", 4 | "title": "援助交配#8", 5 | "episode": 8, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 223000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 324000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 608000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 848000, 22 | "prompt": null 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/39811.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "videoCode": "39811", 4 | "group": "今泉家似乎變成辣妹的聚會所", 5 | "title": "今泉家似乎變成辣妹的聚會所#4", 6 | "episode": 4, 7 | "author": "NeKoOuO", 8 | "keyframes": [ 9 | { 10 | "position": 175000, 11 | "prompt": null 12 | }, 13 | { 14 | "position": 425000, 15 | "prompt": null 16 | }, 17 | { 18 | "position": 629000, 19 | "prompt": null 20 | }, 21 | { 22 | "position": 825000, 23 | "prompt": null 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/84717.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "84717", 3 | "group": "初戀時間", 4 | "title": "初戀時間#1", 5 | "episode": 1, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 72000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 427270, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 499500, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 650000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 840500, 26 | "prompt": null 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/84718.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "84718", 3 | "group": "初戀時間", 4 | "title": "初戀時間#2", 5 | "episode": 2, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 462000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 576500, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 588000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 678500, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 823430, 26 | "prompt": null 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/85926.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "85926", 3 | "group": "初戀時間", 4 | "title": "初戀時間#3", 5 | "episode": 3, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 438000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 602500, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 822500, 18 | "prompt": null 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/85927.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "85927", 3 | "group": "初戀時間", 4 | "title": "初戀時間#4", 5 | "episode": 4, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 376000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 474950, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 633500, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 715000, 22 | "prompt": null 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/87968.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "87968", 3 | "group": "到了異世界就拿出性本事", 4 | "title": "到了異世界就拿出性本事#3", 5 | "episode": 3, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 229500, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 445500, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 637200, 18 | "prompt": null 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/87969.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "87969", 3 | "group": "到了異世界就拿出性本事", 4 | "title": "到了異世界就拿出性本事#4", 5 | "episode": 4, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 474500, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 791000, 14 | "prompt": null 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/89087.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "89087", 3 | "group": "初戀時間", 4 | "title": "初戀時間#5", 5 | "episode": 5, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 482500, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 500500, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 556000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 777300, 22 | "prompt": null 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/assets/h_keyframes/89088.json: -------------------------------------------------------------------------------- 1 | { 2 | "videoCode": "89088", 3 | "group": "初戀時間", 4 | "title": "初戀時間#6", 5 | "episode": 6, 6 | "author": "NeKoOuO", 7 | "keyframes": [ 8 | { 9 | "position": 304000, 10 | "prompt": null 11 | }, 12 | { 13 | "position": 387000, 14 | "prompt": null 15 | }, 16 | { 17 | "position": 546000, 18 | "prompt": null 19 | }, 20 | { 21 | "position": 644000, 22 | "prompt": null 23 | }, 24 | { 25 | "position": 710000, 26 | "prompt": null 27 | }, 28 | { 29 | "position": 808000, 30 | "prompt": null 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/assets/report_reason.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "lang": { 4 | "zh-rCN": "煽动仇恨或恶意内容", 5 | "en": "Inciting hatred or malicious content", 6 | "zh-rTW": "煽動仇恨或惡意內容" 7 | }, 8 | "reason_key": "煽動仇恨或惡意內容" 9 | }, 10 | { 11 | "lang": { 12 | "zh-rCN": "暴力或令人反感的内容", 13 | "en": "Violent or offensive content", 14 | "zh-rTW": "暴力或令人反感的內容" 15 | }, 16 | "reason_key": "暴力或令人反感的內容" 17 | }, 18 | { 19 | "lang": { 20 | "zh-rCN": "广告内容或垃圾内容", 21 | "en": "Advertising content or spam", 22 | "zh-rTW": "廣告內容或垃圾內容" 23 | }, 24 | "reason_key": "廣告內容或垃圾內容" 25 | }, 26 | { 27 | "lang": { 28 | "zh-rCN": "其他检举理由", 29 | "en": "Other reporting reasons", 30 | "zh-rTW": "其他檢舉理由" 31 | }, 32 | "reason_key": "其他檢舉理由" 33 | } 34 | ] -------------------------------------------------------------------------------- /app/src/main/assets/search_options/release_date.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "lang": { 4 | "zh-rCN": "全部", 5 | "en": "All", 6 | "zh-rTW": "全部" 7 | }, 8 | "search_key": null 9 | }, 10 | { 11 | "lang": { 12 | "zh-rCN": "过去24小时", 13 | "en": "Last 24 hours", 14 | "zh-rTW": "過去24小時" 15 | }, 16 | "search_key": "過去 24 小時" 17 | }, 18 | { 19 | "lang": { 20 | "zh-rCN": "过去2天", 21 | "en": "Last 2 days", 22 | "zh-rTW": "過去2天" 23 | }, 24 | "search_key": "過去 2 天" 25 | }, 26 | { 27 | "lang": { 28 | "zh-rCN": "过去1周", 29 | "en": "Last week", 30 | "zh-rTW": "過去1週" 31 | }, 32 | "search_key": "過去 1 週" 33 | }, 34 | { 35 | "lang": { 36 | "zh-rCN": "过去1个月", 37 | "en": "Last month", 38 | "zh-rTW": "過去1個月" 39 | }, 40 | "search_key": "過去 1 個月" 41 | }, 42 | { 43 | "lang": { 44 | "zh-rCN": "过去3个月", 45 | "en": "Last 3 months", 46 | "zh-rTW": "過去3個月" 47 | }, 48 | "search_key": "過去 3 個月" 49 | }, 50 | { 51 | "lang": { 52 | "zh-rCN": "过去1年", 53 | "en": "Past year", 54 | "zh-rTW": "過去1年" 55 | }, 56 | "search_key": "過去 1 年" 57 | } 58 | ] -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/HCrashHandler.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer 2 | 3 | import com.yenaly.yenaly_libs.ActivityManager 4 | 5 | object HCrashHandler : Thread.UncaughtExceptionHandler { 6 | override fun uncaughtException(t: Thread, e: Throwable) { 7 | e.printStackTrace() 8 | ActivityManager.restart(killProcess = true) 9 | } 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/HInitializer.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer 2 | 3 | import android.content.Context 4 | import com.yenaly.yenaly_libs.base.YenalyInitializer 5 | 6 | class HInitializer : YenalyInitializer() { 7 | override fun create(context: Context) { 8 | super.create(context) 9 | // 用于处理 Firebase Crashlytics 初始化 10 | Thread.setDefaultUncaughtExceptionHandler(HCrashHandler) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/dao/CheckInRecordDao.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Insert 5 | import androidx.room.OnConflictStrategy 6 | import androidx.room.Query 7 | import com.yenaly.han1meviewer.logic.entity.CheckInRecordEntity 8 | 9 | @Dao 10 | interface CheckInRecordDao { 11 | @Query("SELECT * FROM check_in_records WHERE date = :date") 12 | suspend fun getRecord(date: String): CheckInRecordEntity? 13 | 14 | @Insert(onConflict = OnConflictStrategy.REPLACE) 15 | suspend fun insertOrUpdate(record: CheckInRecordEntity) 16 | 17 | @Query("SELECT COUNT(*) FROM check_in_records WHERE count > 0 AND date LIKE :yearMonth || '%'") 18 | suspend fun getMonthlyCheckedDays(yearMonth: String): Int 19 | 20 | @Query("SELECT * FROM check_in_records WHERE date BETWEEN :start AND :end") 21 | suspend fun getRecordsBetween(start: String, end: String): List 22 | 23 | @Query("SELECT SUM(count) FROM check_in_records WHERE date LIKE :yearMonth || '%'") 24 | suspend fun getMonthlyCheckInTotal(yearMonth: String): Int? 25 | 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/dao/CheckInRecordDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.dao 2 | 3 | import android.content.Context 4 | import androidx.room.Database 5 | import androidx.room.Room 6 | import androidx.room.RoomDatabase 7 | import com.yenaly.han1meviewer.logic.entity.CheckInRecordEntity 8 | 9 | @Database( 10 | entities = [CheckInRecordEntity::class], 11 | version = 1, 12 | exportSchema = false 13 | ) 14 | abstract class CheckInRecordDatabase : RoomDatabase() { 15 | abstract fun checkInDao(): CheckInRecordDao 16 | 17 | companion object { 18 | @Volatile 19 | private var INSTANCE: CheckInRecordDatabase? = null 20 | 21 | fun getDatabase(context: Context): CheckInRecordDatabase { 22 | return INSTANCE ?: synchronized(this) { 23 | val instance = Room.databaseBuilder( 24 | context.applicationContext, 25 | CheckInRecordDatabase::class.java, 26 | "check_in_records" 27 | ).build() 28 | INSTANCE = instance 29 | instance 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/dao/MiscellanyDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.dao 2 | 3 | import androidx.room.Database 4 | import androidx.room.Room 5 | import androidx.room.RoomDatabase 6 | import com.yenaly.han1meviewer.logic.entity.HKeyframeEntity 7 | import com.yenaly.yenaly_libs.utils.applicationContext 8 | 9 | /** 10 | * 这是各种 有数据库需求的小功能 的聚集地, 11 | * 如果这个功能需要数据库就放到这里。 12 | * 13 | * @project Han1meViewer 14 | * @author Yenaly Liew 15 | * @time 2023/11/12 012 12:28 16 | */ 17 | @Database( 18 | entities = [HKeyframeEntity::class], 19 | version = 1, exportSchema = false 20 | ) 21 | abstract class MiscellanyDatabase : RoomDatabase() { 22 | 23 | abstract val hKeyframeDao: HKeyframeDao 24 | 25 | companion object { 26 | val instance by lazy { 27 | Room.databaseBuilder( 28 | applicationContext, 29 | MiscellanyDatabase::class.java, 30 | "miscellany.db" 31 | ).build() 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/dao/download/DownloadCategoryDao.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.dao.download 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import androidx.room.RewriteQueriesToDropUnusedColumns 6 | import androidx.room.Transaction 7 | import com.yenaly.han1meviewer.logic.entity.download.DownloadCategoryEntity 8 | import com.yenaly.han1meviewer.logic.entity.download.HanimeDownloadEntity 9 | import kotlinx.coroutines.flow.Flow 10 | 11 | @Dao 12 | abstract class DownloadCategoryDao { 13 | @RewriteQueriesToDropUnusedColumns 14 | @Transaction 15 | @Query( 16 | "SELECT * FROM HanimeDownloadEntity " + 17 | "INNER JOIN HanimeCategoryCrossRef ON HanimeDownloadEntity.id = HanimeCategoryCrossRef.videoId " + 18 | "WHERE HanimeCategoryCrossRef.categoryId = :categoryId AND HanimeDownloadEntity.downloadedLength == HanimeDownloadEntity.length" 19 | ) 20 | abstract fun getVideosForCategory(categoryId: Int): Flow> 21 | 22 | @Query("SELECT * FROM DownloadCategoryEntity") 23 | abstract fun getAllCategories(): Flow> 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/entity/CheckInRecordEntity.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.entity 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "check_in_records") 7 | data class CheckInRecordEntity( 8 | @PrimaryKey val date: String, 9 | val count: Int 10 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/entity/SearchHistoryEntity.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.entity 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | /** 7 | * @project Hanime1 8 | * @author Yenaly Liew 9 | * @time 2022/06/22 022 18:16 10 | */ 11 | @Entity 12 | data class SearchHistoryEntity( 13 | val query: String, 14 | @PrimaryKey(autoGenerate = true) 15 | val id: Int = 0 16 | ) 17 | 18 | @Entity(tableName = "HanimeAdvancedSearchHistory") 19 | data class HanimeAdvancedSearchHistoryEntity( 20 | @PrimaryKey(autoGenerate = true) val id: Long = 0, 21 | val query: String? = null, 22 | val genre: String? = null, 23 | val sort: String? = null, 24 | val broad: Boolean? = null, 25 | val date: String? = null, 26 | val duration: String? = null, 27 | val tags: String? = null, 28 | val brands: String? = null, 29 | val createdAt: Long = System.currentTimeMillis() 30 | ) 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/entity/WatchHistoryEntity.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.entity 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | /** 7 | * @project Han1meViewer 8 | * @author Yenaly Liew 9 | * @time 2022/07/02 002 13:13 10 | */ 11 | @Entity 12 | data class WatchHistoryEntity( 13 | val coverUrl: String, 14 | val title: String, 15 | val releaseDate: Long, 16 | val watchDate: Long, 17 | val videoCode: String, 18 | val progress: Long = 0L, 19 | @PrimaryKey(autoGenerate = true) 20 | val id: Int = 0, 21 | ) { 22 | 23 | val releaseDateDays: Int 24 | get() = (releaseDate / (24 * 60 * 60 * 1000)).toInt() 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/entity/download/DownloadCategoryEntity.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.entity.download 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity 7 | data class DownloadCategoryEntity( 8 | val name: String, 9 | @PrimaryKey(autoGenerate = true) 10 | val id: Int = 0, 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/entity/download/HanimeCategoryCrossRef.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.entity.download 2 | 3 | import androidx.room.Entity 4 | import androidx.room.Index 5 | 6 | @Entity( 7 | primaryKeys = ["videoId", "categoryId"], 8 | indices = [Index(value = ["categoryId"])], 9 | ) 10 | data class HanimeCategoryCrossRef( 11 | val videoId: Int, 12 | val categoryId: Int, 13 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/entity/download/VideoWithCategories.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.entity.download 2 | 3 | import androidx.room.Embedded 4 | import androidx.room.Junction 5 | import androidx.room.Relation 6 | 7 | data class VideoWithCategories( 8 | @Embedded 9 | val video: HanimeDownloadEntity, 10 | @Relation( 11 | parentColumn = "id", 12 | entityColumn = "id", 13 | associateBy = Junction( 14 | value = HanimeCategoryCrossRef::class, 15 | parentColumn = "videoId", 16 | entityColumn = "categoryId" 17 | ) 18 | ) 19 | val categories: List, 20 | ) 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/exception/CloudFlareBlockedException.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.exception 2 | 3 | import com.yenaly.han1meviewer.R 4 | 5 | /** 6 | * 检测到爬虫被封鎖 7 | * 8 | * @project Han1meViewer 9 | * @author Yenaly Liew 10 | * @time 2023/08/07 007 12:45 11 | */ 12 | open class CloudFlareBlockedException(reason: String) : RuntimeException(reason) { 13 | companion object { 14 | val localizedMessages = intArrayOf( 15 | R.string.website_blocked_msg, 16 | R.string.website_blocked_msg_2, 17 | R.string.website_blocked_msg_3, 18 | ) 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/exception/HanimeNotFoundException.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.exception 2 | 3 | /** 4 | * @project Han1meViewer 5 | * @author Yenaly Liew 6 | * @time 2023/08/07 007 13:08 7 | */ 8 | class HanimeNotFoundException(reason: String) : RuntimeException(reason) -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/exception/IPBlockedException.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.exception 2 | 3 | /** 4 | * IP被封鎖 5 | * 6 | * @project Han1meViewer 7 | * @author Yenaly Liew 8 | * @time 2023/08/07 007 12:40 9 | */ 10 | class IPBlockedException(reason: String) : CloudFlareBlockedException(reason) -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/exception/ParseException.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.exception 2 | 3 | /** 4 | * 解析錯誤 5 | * 6 | * @project Han1meViewer 7 | * @author Yenaly Liew 8 | * @time 2023/08/05 005 16:20 9 | */ 10 | class ParseException : RuntimeException { 11 | 12 | constructor( 13 | funcName: String, 14 | varName: String 15 | ) : super("[Parse::$funcName => $varName] parse error!") 16 | 17 | constructor(reason: String) : super(reason) 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/HanimeInfo.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | /** 4 | * @project Han1meViewer 5 | * @author Yenaly Liew 6 | */ 7 | interface HanimeInfoType : MultiItemEntity 8 | 9 | /** 10 | * @project Han1meViewer 11 | * @author Yenaly Liew 12 | * @time 2022/06/08 008 22:56 13 | */ 14 | data class HanimeInfo( 15 | override val title: String, 16 | override val coverUrl: String, 17 | override val videoCode: String, 18 | override val duration: String? = null, 19 | val artist: String? = null, 20 | override val views: String? = null, 21 | val uploadTime: String? = null, 22 | val genre: String? = null, 23 | 24 | val isPlaying: Boolean = false, // for video playlist only. 25 | 26 | override var itemType: Int, 27 | override val reviews: String? = "", 28 | override val currentArtist: String? = "", 29 | val watched: Boolean ?= false, 30 | ): VideoItemType , HanimeInfoType { 31 | companion object { 32 | const val NORMAL = 0 33 | const val SIMPLIFIED = 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/HanimePreview.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | /** 4 | * @project Hanime1 5 | * @author Yenaly Liew 6 | * @time 2022/06/24 024 15:05 7 | */ 8 | data class HanimePreview( 9 | val headerPicUrl: String?, 10 | val hasPrevious: Boolean = false, 11 | val hasNext: Boolean = false, 12 | val latestHanime: List, 13 | val previewInfo: List, 14 | ) { 15 | data class PreviewInfo( 16 | val title: String?, 17 | val videoTitle: String?, 18 | val coverUrl: String?, 19 | val introduction: String?, 20 | val brand: String?, 21 | val releaseDate: String?, 22 | val videoCode: String?, 23 | val tags: List, 24 | val relatedPicsUrl: List, 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/MultiItemEntity.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | /** 4 | * @project Han1meViewer 5 | * @author Yenaly Liew 6 | * @time 2023/11/26 026 17:40 7 | */ 8 | interface MultiItemEntity { 9 | val itemType: Int 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/MyListItems.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | /** 4 | * @project Han1meViewer 5 | * @author Yenaly Liew 6 | * @time 2022/07/05 005 15:30 7 | */ 8 | data class MyListItems( 9 | val hanimeInfo: List, 10 | /** 11 | * 清單的介紹,一般用於播放清單 12 | */ 13 | var desc: String? = null, 14 | val csrfToken: String? = null, 15 | ) 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/MySubscriptions.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | import android.os.Parcelable 4 | import kotlinx.parcelize.Parcelize 5 | 6 | @Parcelize 7 | data class MySubscriptions( 8 | val subscriptions: List, 9 | val subscriptionsVideos: List, 10 | val maxPage: Int 11 | ) : Parcelable 12 | 13 | @Parcelize 14 | data class SubscriptionItem( 15 | val artistName: String, 16 | val avatar: String 17 | ) : Parcelable 18 | 19 | @Parcelize 20 | data class SubscriptionVideosItem( 21 | override val title: String, 22 | override val coverUrl: String, 23 | override val videoCode: String, 24 | override val duration: String? = null, 25 | override val views: String? = null, 26 | override val reviews: String? = null, 27 | override val currentArtist: String? = null 28 | ) : Parcelable, VideoItemType 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/ParamEnum.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | import com.yenaly.han1meviewer.EMPTY_STRING 4 | 5 | enum class MyListType(val value: String) { 6 | FAV_VIDEO("LL"), 7 | WATCH_LATER("WL"), 8 | SUBSCRIPTION("SL") 9 | } 10 | 11 | enum class FavStatus(val value: String) { 12 | ADD_FAV(EMPTY_STRING), 13 | CANCEL_FAV("1") 14 | } 15 | 16 | enum class CommentPlace(val value: String) { 17 | COMMENT("comment"), // 主評論 18 | CHILD_COMMENT("reply") // 子評論 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/Playlists.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | /** 4 | * @project Han1meViewer 5 | * @author Yenaly Liew 6 | * @time 2023/08/26 026 17:47 7 | */ 8 | data class Playlists( 9 | val playlists: List, 10 | val csrfToken: String? = null, 11 | ) { 12 | data class Playlist( 13 | val listCode: String, 14 | var title: String, 15 | var total: Int, 16 | val coverUrl: String? = null 17 | ) 18 | } 19 | 20 | /** 21 | * 用於 修改播放清單 Flow 的返回值 22 | */ 23 | data class ModifiedPlaylistArgs( 24 | var title: String, 25 | var desc: String, 26 | var isDeleted: Boolean, 27 | ) 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/SearchTag.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | /** 4 | * @project Hanime1 5 | * @author Yenaly Liew 6 | * @time 2022/06/09 009 21:27 7 | */ 8 | data class SearchTag( 9 | val genres: List, 10 | val tags: Map>, 11 | val sortOptions: List, 12 | val brands: List, 13 | val releaseDates: ReleaseDate, 14 | val durationOptions: List>, 15 | ) { 16 | data class ReleaseDate( 17 | val years: List>, 18 | val months: List>, 19 | ) 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/VideoItemType.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model 2 | 3 | interface VideoItemType { 4 | val title: String 5 | val coverUrl: String 6 | val videoCode: String 7 | val duration: String? 8 | val views: String? 9 | val reviews: String? 10 | val currentArtist: String? 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/github/Commit.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model.github 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class CommitComparison(val commits: List) { 7 | @Serializable 8 | data class Commit(val commit: CommitDetail) { 9 | @Serializable 10 | data class CommitDetail(val author: CommitAuthor, val message: String) { 11 | @Serializable 12 | data class CommitAuthor(val name: String) 13 | } 14 | } 15 | } 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/github/Latest.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model.github 2 | 3 | /** 4 | * @project Han1meViewer 5 | * @author Yenaly Liew 6 | * @time 2024/03/21 021 08:56 7 | */ 8 | data class Latest( 9 | val version: String, 10 | val changelog: String, 11 | val downloadLink: String, 12 | /** 13 | * Node ID for the download link 14 | * 15 | * 其实就是个变相的 md5 验证 16 | */ 17 | val nodeId: String, 18 | ) 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/model/github/Workflow.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.model.github 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | /** 7 | * @project Han1meViewer 8 | * @author Yenaly Liew 9 | * @time 2024/03/21 021 09:03 10 | */ 11 | @Serializable 12 | data class WorkflowRuns( 13 | @SerialName("workflow_runs") val workflowRuns: List, 14 | ) { 15 | @Serializable 16 | data class WorkflowRun( 17 | @SerialName("head_sha") val headSha: String, 18 | @SerialName("display_title") val title: String, 19 | @SerialName("artifacts_url") val artifactsUrl: String, 20 | ) 21 | } 22 | 23 | 24 | @Serializable 25 | data class Artifacts( 26 | @SerialName("artifacts") val artifacts: List, 27 | ) { 28 | val downloadLink: String get() = artifacts.first().downloadLink 29 | val nodeId: String get() = artifacts.first().nodeId 30 | 31 | @Serializable 32 | data class Artifact( 33 | val name: String, 34 | @SerialName("archive_download_url") val downloadLink: String, 35 | @SerialName("node_id") val nodeId: String, 36 | ) 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/network/GitHubDns.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.network 2 | 3 | import okhttp3.Dns 4 | import java.net.InetAddress 5 | 6 | /** 7 | * @project Han1meViewer 8 | * @author Yenaly Liew 9 | * @time 2024/03/29 029 17:14 10 | */ 11 | object GitHubDns : Dns { 12 | override fun lookup(hostname: String): List { 13 | return when (hostname) { 14 | "api.github.com" -> listOf( 15 | InetAddress.getByName("140.82.116.6"), 16 | InetAddress.getByName("20.205.243.168"), 17 | InetAddress.getByName("140.82.121.6") 18 | ) 19 | "github.com" -> listOf( 20 | InetAddress.getByName("20.205.243.166"), 21 | InetAddress.getByName("140.82.121.3"), 22 | InetAddress.getByName("140.82.116.4"), 23 | InetAddress.getByName("140.82.121.4") 24 | ) 25 | else -> Dns.SYSTEM.lookup(hostname) 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/network/interceptor/SpeedLimitInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.network.interceptor 2 | 3 | import okhttp3.Interceptor 4 | import okhttp3.Response 5 | 6 | class SpeedLimitInterceptor(var maxSpeed: Long) : Interceptor { 7 | 8 | companion object { 9 | const val NO_LIMIT = 0L 10 | 11 | const val NO_LIMIT_INDEX = 0 12 | 13 | @JvmField 14 | val SPEED_BYTES = longArrayOf( 15 | /* 不限速 */ 0L, 16 | 128 * 1024L, 256 * 1024L, 512 * 1024L, 17 | 1024 * 1024L, 2048 * 1024L, 4096 * 1024L, 18 | 8192 * 1024L, 10240 * 1024L 19 | ) 20 | } 21 | 22 | override fun intercept(chain: Interceptor.Chain): Response { 23 | val response = chain.proceed(chain.request()) 24 | return response.newBuilder() 25 | .body(response.body?.let { 26 | SpeedLimitResponseBody(it, maxSpeed) 27 | }).build() 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/network/interceptor/SpeedLimitResponseBody.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.network.interceptor 2 | 3 | import com.yenaly.yenaly_libs.utils.unsafeLazy 4 | import okhttp3.ResponseBody 5 | import okio.Throttler 6 | import okio.buffer 7 | 8 | class SpeedLimitResponseBody( 9 | private val responseBody: ResponseBody, 10 | /** 11 | * 0 means no limit 12 | */ 13 | private val maxSpeed: Long 14 | ) : ResponseBody() { 15 | 16 | private val throttler by unsafeLazy { 17 | Throttler().apply { bytesPerSecond(maxSpeed) } 18 | } 19 | 20 | override fun contentLength(): Long = responseBody.contentLength() 21 | 22 | override fun contentType() = responseBody.contentType() 23 | 24 | override fun source() = throttler.source(responseBody.source()).buffer() 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/network/interceptor/UrlLoggingInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.network.interceptor 2 | 3 | import android.util.Log 4 | import okhttp3.Interceptor 5 | import okhttp3.Response 6 | import java.net.URLDecoder 7 | import java.nio.charset.StandardCharsets 8 | 9 | class UrlLoggingInterceptor : Interceptor { 10 | override fun intercept(chain: Interceptor.Chain): Response { 11 | val request = chain.request() 12 | val url = request.url.toString() 13 | val decodedUrl = URLDecoder.decode(url, StandardCharsets.UTF_8.name()) 14 | Log.i("NetworkRequest",decodedUrl) 15 | return chain.proceed(request) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/network/interceptor/UserAgentInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.network.interceptor 2 | 3 | import com.yenaly.han1meviewer.USER_AGENT 4 | import okhttp3.Interceptor 5 | import okhttp3.Response 6 | 7 | object UserAgentInterceptor : Interceptor { 8 | override fun intercept(chain: Interceptor.Chain): Response { 9 | val request = chain.request().newBuilder().addHeader( 10 | "User-Agent", USER_AGENT 11 | ).build() 12 | return chain.proceed(request) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/network/service/HanimeSubscriptionService.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.network.service 2 | 3 | import okhttp3.ResponseBody 4 | import retrofit2.Response 5 | import retrofit2.http.Field 6 | import retrofit2.http.FormUrlEncoded 7 | import retrofit2.http.Header 8 | import retrofit2.http.POST 9 | 10 | interface HanimeSubscriptionService { 11 | 12 | @FormUrlEncoded 13 | @POST("subscribe") 14 | suspend fun subscribeArtist( 15 | @Field("_token") csrfToken: String?, 16 | @Field("subscribe-user-id") userId: String, 17 | @Field("subscribe-artist-id") artistId: String, 18 | // 如果当前未订阅会发送空字符串,否则发1 19 | @Field("subscribe-status") status: String, 20 | @Header("X-CSRF-TOKEN") csrfToken_1: String? = csrfToken, 21 | ): Response 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/state/PageLoadingState.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.state 2 | 3 | /** 4 | * @project Hanime1 5 | * @author Yenaly Liew 6 | * @time 2022/06/10 010 16:30 7 | */ 8 | sealed class PageLoadingState { 9 | data class Success(val info: T) : PageLoadingState() 10 | data object Loading : PageLoadingState() 11 | data object NoMoreData : PageLoadingState() 12 | data class Error(val throwable: Throwable) : PageLoadingState() 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/state/VideoLoadingState.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.state 2 | 3 | /** 4 | * @project Hanime1 5 | * @author Yenaly Liew 6 | * @time 2022/06/18 018 18:14 7 | */ 8 | sealed class VideoLoadingState { 9 | data class Success(val info: T) : VideoLoadingState() 10 | data class Error(val throwable: Throwable) : VideoLoadingState() 11 | data object Loading : VideoLoadingState() 12 | data object NoContent : VideoLoadingState() 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/logic/state/WebsiteState.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.logic.state 2 | 3 | /** 4 | * @project Hanime1 5 | * @author Yenaly Liew 6 | * @time 2022/06/08 008 22:20 7 | */ 8 | sealed class WebsiteState { 9 | data class Success(val info: T) : WebsiteState() 10 | data object Loading : WebsiteState() 11 | data class Error(val throwable: Throwable) : WebsiteState() 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/StateLayoutMixin.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui 2 | 3 | import android.annotation.SuppressLint 4 | import android.widget.TextView 5 | import com.drake.statelayout.StateLayout 6 | import com.yenaly.han1meviewer.R 7 | import com.yenaly.han1meviewer.pienization 8 | 9 | /** 10 | * 用於初始化 StateLayout。 11 | * 12 | * 但是不是説實現了這個接口就代表有 StateLayout 了,有些我還是直接用的 BRVAH 自帶的 StateLayoutVH, 13 | * 因爲用 StateLayout 稍稍有點麻煩。 14 | * 15 | * @project Han1meViewer 16 | * @author Yenaly Liew 17 | * @time 2023/11/30 030 15:24 18 | */ 19 | @JvmDefaultWithoutCompatibility 20 | interface StateLayoutMixin { 21 | 22 | /** 23 | * 初始化 StateLayout 24 | */ 25 | @SuppressLint("SetTextI18n") 26 | fun StateLayout.init(apply: StateLayout.() -> Unit = {}) { 27 | errorLayout = R.layout.layout_empty_view 28 | emptyLayout = R.layout.layout_empty_view 29 | onError { 30 | val err = it as Throwable 31 | findViewById(R.id.tv_empty).text = err.pienization 32 | } 33 | apply() 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/adapter/AdapterLikeDataBindingPage.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.adapter 2 | 3 | import androidx.databinding.ViewDataBinding 4 | 5 | /** 6 | * 利用 Adapter 性质的页面,同时运用 DataBinding 7 | */ 8 | interface AdapterLikeDataBindingPage { 9 | var binding: DB? 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/adapter/FixedGridLayoutManager.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.adapter 2 | 3 | import android.content.Context 4 | import androidx.recyclerview.widget.GridLayoutManager 5 | 6 | /** 7 | * @project Han1meViewer 8 | * @author Yenaly Liew 9 | * @time 2022/09/10 010 00:24 10 | */ 11 | class FixedGridLayoutManager( 12 | context: Context?, 13 | spanCount: Int 14 | ) : GridLayoutManager(context, spanCount) { 15 | override fun supportsPredictiveItemAnimations(): Boolean { 16 | return false 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/fragment/IToolbarFragment.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.fragment 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | 5 | /** 6 | * 用於 Fragment 要求 Activity 實現 Toolbar 的接口 7 | * 8 | * @project Han1meViewer 9 | * @author Yenaly Liew 10 | * @time 2023/08/27 027 16:29 11 | */ 12 | interface IToolbarFragment { 13 | 14 | /** 15 | * 設置 Toolbar 16 | */ 17 | fun T.setupToolbar() 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/fragment/LoginNeededFragmentMixin.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.fragment 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.navigation.fragment.findNavController 5 | import com.yenaly.han1meviewer.Preferences.isAlreadyLogin 6 | 7 | /** 8 | * 用於需要登錄的 Fragment 9 | * 10 | * @project Han1meViewer 11 | * @author Yenaly Liew 12 | * @time 2023/08/29 029 15:32 13 | */ 14 | @JvmDefaultWithoutCompatibility 15 | interface LoginNeededFragmentMixin { 16 | /** 17 | * 檢查是否已經登錄,如果沒有則返回上一個 Fragment 18 | */ 19 | fun Fragment.checkLogin() { 20 | if (!isAlreadyLogin) { 21 | findNavController().navigateUp() 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/fragment/PermissionRequester.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.fragment 2 | 3 | interface PermissionRequester { 4 | fun requestStoragePermission( 5 | onGranted: () -> Unit, 6 | onDenied: () -> Unit, 7 | onPermanentlyDenied: () -> Unit 8 | ) 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/fragment/ToolbarHost.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.fragment 2 | 3 | interface ToolbarHost { 4 | fun setupToolbar(title: CharSequence, canNavigateBack: Boolean = true) 5 | fun hideToolbar() 6 | fun showToolbar() 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/fragment/funny/FunnyTouchListener.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.fragment.funny 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.view.MotionEvent 6 | import android.view.View 7 | 8 | class FunnyTouchListener ( 9 | context: Context, 10 | onTrigger: () -> Unit 11 | ) : View.OnTouchListener { 12 | 13 | private val detector = SomeFunny(context,onTrigger) 14 | 15 | @SuppressLint("ClickableViewAccessibility") 16 | override fun onTouch(v: View, event: MotionEvent): Boolean { 17 | return detector.handleMotionEvent(event) 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/view/LinearSmoothToStartScroller.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.view 2 | 3 | import android.content.Context 4 | import androidx.recyclerview.widget.LinearSmoothScroller 5 | 6 | /** 7 | * https://stackoverflow.com/questions/31235183 8 | * 9 | * @project Han1meViewer 10 | * @author Yenaly Liew 11 | * @time 2024/04/04 004 17:49 12 | */ 13 | class LinearSmoothToStartScroller(context: Context?) : LinearSmoothScroller(context) { 14 | override fun getVerticalSnapPreference(): Int = SNAP_TO_START 15 | 16 | override fun getHorizontalSnapPreference(): Int = SNAP_TO_START 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/view/funcbar/Hanidokitem.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.view.funcbar 2 | 3 | import android.view.View.OnClickListener 4 | import androidx.annotation.DrawableRes 5 | import androidx.annotation.StringRes 6 | 7 | /** 8 | * @project Han1meViewer 9 | * @author Yenaly Liew 10 | * @since 2025/3/11 22:10 11 | */ 12 | data class Hanidokitem( 13 | @param:DrawableRes var icon: Int = 0, 14 | @param:StringRes var text: Int = 0, 15 | var viewAction: OnClickListener? = null, 16 | var subitems: List = emptyList(), 17 | private val _isBack: Boolean = false, 18 | ) { 19 | 20 | val isBack: Boolean 21 | get() = this._isBack 22 | 23 | infix fun contentEquals(other: Hanidokitem): Boolean = icon == other.icon && text == other.text 24 | 25 | companion object { 26 | @JvmStatic 27 | inline fun create(action: Hanidokitem.() -> Unit): Hanidokitem = Hanidokitem().apply(action) 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/viewmodel/IHCsrfToken.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.viewmodel 2 | 3 | interface IHCsrfToken { 4 | var csrfToken: String? 5 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/viewmodel/MyListViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.viewmodel 2 | 3 | import android.app.Application 4 | import com.yenaly.han1meviewer.ui.viewmodel.mylist.FavSubViewModel 5 | import com.yenaly.han1meviewer.ui.viewmodel.mylist.PlaylistSubViewModel 6 | import com.yenaly.han1meviewer.ui.viewmodel.mylist.WatchLaterSubViewModel 7 | import com.yenaly.yenaly_libs.base.YenalyViewModel 8 | 9 | /** 10 | * @project Han1meViewer 11 | * @author Yenaly Liew 12 | * @time 2022/07/04 004 22:46 13 | */ 14 | class MyListViewModel(application: Application) : YenalyViewModel(application) { 15 | 16 | val playlist by sub() 17 | val watchLater by sub() 18 | val fav by sub() 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/ui/viewmodel/PreviewViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.ui.viewmodel 2 | 3 | import android.app.Application 4 | import androidx.lifecycle.viewModelScope 5 | import com.yenaly.han1meviewer.logic.NetworkRepo 6 | import com.yenaly.han1meviewer.logic.model.HanimePreview 7 | import com.yenaly.han1meviewer.logic.state.WebsiteState 8 | import com.yenaly.yenaly_libs.base.YenalyViewModel 9 | import kotlinx.coroutines.flow.MutableStateFlow 10 | import kotlinx.coroutines.flow.asStateFlow 11 | import kotlinx.coroutines.launch 12 | 13 | /** 14 | * @project Hanime1 15 | * @author Yenaly Liew 16 | * @time 2022/06/23 023 16:47 17 | */ 18 | class PreviewViewModel(application: Application) : YenalyViewModel(application) { 19 | 20 | private val _previewFlow = 21 | MutableStateFlow>(WebsiteState.Loading) 22 | val previewFlow = _previewFlow.asStateFlow() 23 | 24 | fun getHanimePreview(date: String) { 25 | viewModelScope.launch { 26 | NetworkRepo.getHanimePreview(date).collect { preview -> 27 | _previewFlow.value = preview 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/util/Colors.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.util 2 | 3 | import android.content.res.ColorStateList 4 | import androidx.annotation.ColorInt 5 | 6 | fun @receiver:ColorInt Int.toColorStateList() = ColorStateList.valueOf(this) -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/util/Firebases.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.util 2 | 3 | import android.app.Activity 4 | import android.util.Log 5 | import androidx.fragment.app.Fragment 6 | import com.google.firebase.Firebase 7 | import com.google.firebase.analytics.FirebaseAnalytics 8 | import com.google.firebase.analytics.analytics 9 | import com.google.firebase.analytics.logEvent 10 | 11 | fun Activity.logScreenViewEvent(fragment: Fragment) { 12 | Firebase.analytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW) { 13 | // example: MainActivity-HomePageFragment 14 | val screenName = this@logScreenViewEvent.javaClass.simpleName + 15 | "-" + fragment.javaClass.simpleName 16 | Log.d("logScreenViewEvent", "screenName: $screenName") 17 | param(FirebaseAnalytics.Param.SCREEN_NAME, screenName) 18 | param(FirebaseAnalytics.Param.SCREEN_CLASS, fragment.javaClass.simpleName) 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/util/Parcels.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.util 2 | 3 | import android.os.Parcel 4 | 5 | @Suppress("NOTHING_TO_INLINE") 6 | inline fun Parcel.readBooleanCompat(): Boolean { 7 | return readInt() != 0 8 | } 9 | 10 | @Suppress("NOTHING_TO_INLINE") 11 | inline fun Parcel.writeBooleanCompat(value: Boolean) { 12 | writeInt(if (value) 1 else 0) 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/util/Preferences.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.util 2 | 3 | import androidx.preference.SeekBarPreference 4 | 5 | fun SeekBarPreference.setSummaryConverter( 6 | defValue: Int, 7 | converter: (Int) -> CharSequence?, 8 | action: ((Int) -> Unit)? = null 9 | ) { 10 | setDefaultValue(defValue) 11 | summary = converter(value) 12 | setOnPreferenceChangeListener { _, newValue -> 13 | summary = converter(newValue as Int) 14 | action?.invoke(newValue) 15 | true 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yenaly/han1meviewer/worker/WorkerMixin.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer.worker 2 | 3 | import androidx.work.ListenableWorker 4 | import com.yenaly.yenaly_libs.utils.unsafeLazy 5 | 6 | /** 7 | * @project Han1meViewer 8 | * @author Yenaly Liew 9 | * @time 2024/03/22 022 21:33 10 | */ 11 | @JvmDefaultWithoutCompatibility 12 | interface WorkerMixin { 13 | @Suppress("UNCHECKED_CAST", "SameParameterValue") 14 | fun ListenableWorker.inputData(key: String, def: T): Lazy = unsafeLazy { 15 | when (def) { 16 | is String -> (inputData.getString(key) ?: def) as T 17 | is Int -> inputData.getInt(key, def) as T 18 | is Long -> inputData.getLong(key, def) as T 19 | is Boolean -> inputData.getBoolean(key, def) as T 20 | is Float -> inputData.getFloat(key, def) as T 21 | else -> throw IllegalArgumentException("Unsupported type") 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/color/nav_item_icon_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/color/nav_item_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/akarin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/akarin.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/apply_deep_links.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/apply_deep_links.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_add_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_add_link_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_arrow_forward_ios_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_bug_report_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_cert_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_count_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_data_usage_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_deband_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_decoder_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_delay_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_edit_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_error_outline_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_export_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_format_list_bulleted_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_forum_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_frame_jump_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_h_24.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_hosts_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_keyboard_arrow_down_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_keyboard_arrow_up_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_manage_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_more_horiz_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_overtime_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_player_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_prohibit_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_refresh_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_remove_circle_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_seek_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_share_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_share_first_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_sort_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_speed_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_vpn_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_default_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/bg_default_header.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/cookies_intro1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/cookies_intro1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/frosted_glass.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/gradient_black_transparent_90.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_4k_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_access_time_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_arrow_back_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_arrow_forward_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_cancel_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_check_circle_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_clear_all_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_close_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_comment_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_delete_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_disable_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_download_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_favorite_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_favorite_border_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_help_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_history_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_home_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_info_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_list_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_mask.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_moon_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_more_time_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_newspaper_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_pause_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_pause_24_tintwhite.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_play_arrow_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_play_arrow_24_tintwhite.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_play_circle_outline_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_reply_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_report_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_scan_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_search_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_send_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_settings_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_share_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_skip_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_theme_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_thumb_down_alt_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_thumb_down_off_alt_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_thumb_up_alt_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_thumb_up_off_alt_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_update_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_watch_later_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clock.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_ext_link.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_calc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/ic_launcher_calc.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_cornhub.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/ic_launcher_cornhub.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_xxt.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/ic_launcher_xxt.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pip_mode.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_send_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_setting_applock.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_setting_ci.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_subscribtion.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_circle_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/indicator_active.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/indicator_inactive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/linear_gradient_90.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/linear_gradient_90_notrans.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/neuro_sad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/drawable/neuro_sad.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_home_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/scaled_added_time.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search_bar_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_download_func_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_preview_button_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_preview_button_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_title_mask.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_video.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/base_column_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 22 | 23 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/delay_test_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_list_only.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_video_introduction.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_hanidock.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_hanime_preview_news_pic.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_preview_tour_simplified.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_rv_wrapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_simple_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_video_column_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_video_tag_chip.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/jz_layout_speed.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_empty_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_hanidock.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_rv_scrollbars.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nav_header_ability.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_comment_sort.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_downloading_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 15 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_my_list_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_playlist_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_preview_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_watch_history_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_calc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_calc_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_cornhub.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_cornhub_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_debug.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_debug_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_xxt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_xxt_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_calc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_calc.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_calc_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_calc_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_cornhub.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_cornhub.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_cornhub_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_cornhub_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_debug.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_debug.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_debug_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_debug_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_xxt.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_xxt.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_xxt_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_xxt_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_xxt_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-hdpi/ic_launcher_xxt_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_calc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_calc.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_calc_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_calc_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_cornhub.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_cornhub.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_cornhub_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_cornhub_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_debug.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_debug.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_debug_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_debug_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_xxt.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_xxt.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_xxt_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_xxt_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_xxt_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-mdpi/ic_launcher_xxt_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_calc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_calc.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_calc_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_calc_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_cornhub.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_cornhub.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_cornhub_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_cornhub_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_debug.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_debug.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_debug_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_debug_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_xxt.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_xxt.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_xxt_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_xxt_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_xxt_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xhdpi/ic_launcher_xxt_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_calc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_calc.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_calc_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_calc_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_calc_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_calc_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_cornhub.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_cornhub.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_cornhub_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_cornhub_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_cornhub_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_cornhub_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_debug.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_debug.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_debug_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_debug_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_debug_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_debug_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxhdpi/ic_launcher_xxt_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_calc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_calc.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_calc_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_calc_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_calc_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_calc_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_cornhub.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_cornhub.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_cornhub_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_cornhub_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_cornhub_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_cornhub_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_debug.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_debug.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_debug_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_debug_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_debug_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_debug_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/mipmap-xxxhdpi/ic_launcher_xxt_round.webp -------------------------------------------------------------------------------- /app/src/main/res/raw/akarin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/app/src/main/res/raw/akarin.png -------------------------------------------------------------------------------- /app/src/main/res/values-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 30dp 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #212121 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_calc_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBFD4 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_cornhub_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | 15 | 18 | 21 | -------------------------------------------------------------------------------- /app/src/test/java/com/yenaly/han1meviewer/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.han1meviewer 2 | 3 | import org.junit.Assert.assertEquals 4 | import org.junit.Test 5 | 6 | /** 7 | * Example local unit test, which will execute on the development machine (host). 8 | * 9 | * See [testing documentation](http://d.android.com/tools/testing). 10 | */ 11 | class ExampleUnitTest { 12 | @Test 13 | fun addition_isCorrect() { 14 | assertEquals(4, 2 + 2) 15 | } 16 | } -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | alias(libs.plugins.com.android.application) apply false 4 | alias(libs.plugins.com.android.library) apply false 5 | alias(libs.plugins.org.jetbrains.kotlin.android) apply false 6 | alias(libs.plugins.org.jetbrains.kotlin.plugin.serialization) apply false 7 | alias(libs.plugins.org.jetbrains.kotlin.plugin.parcelize) apply false 8 | alias(libs.plugins.com.google.gms.google.services) apply false 9 | alias(libs.plugins.com.google.firebase.crashlytics) apply false 10 | alias(libs.plugins.com.google.firebase.firebase.pref) apply false 11 | alias(libs.plugins.compose.compiler) apply false 12 | } 13 | 14 | tasks.register("clean") { 15 | delete(rootProject.layout.buildDirectory) 16 | } -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | google() 8 | maven("https://jitpack.io") 9 | } -------------------------------------------------------------------------------- /develop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/develop -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon May 13 16:01:02 CST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | #distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip 5 | distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.13-bin.zip 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /icon/icon_han1me_viewer-rurires.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/icon/icon_han1me_viewer-rurires.png -------------------------------------------------------------------------------- /icon/icon_transparent_han1me_viewer-rurires.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/icon/icon_transparent_han1me_viewer-rurires.png -------------------------------------------------------------------------------- /readme_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/readme_01.png -------------------------------------------------------------------------------- /readme_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/readme_02.png -------------------------------------------------------------------------------- /readme_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/readme_03.png -------------------------------------------------------------------------------- /readme_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/readme_04.png -------------------------------------------------------------------------------- /readme_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/readme_05.png -------------------------------------------------------------------------------- /readme_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/readme_06.png -------------------------------------------------------------------------------- /readme_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/readme_07.png -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | maven { url = uri("https://jitpack.io/") } 14 | } 15 | } 16 | rootProject.name = "Han1meViewer" 17 | include(":app", ":yenaly_libs") 18 | -------------------------------------------------------------------------------- /yenaly_libs/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /yenaly_libs/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misaka10032w/Han1meViewer/47abe9f788babdc823132525b67306f78e0cca55/yenaly_libs/consumer-rules.pro -------------------------------------------------------------------------------- /yenaly_libs/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -keepattributes SourceFile, LineNumberTable 24 | -dontwarn java.lang.invoke.StringConcatFactory 25 | -keep class com.yenaly.yenaly_libs.** { *; } -------------------------------------------------------------------------------- /yenaly_libs/src/androidTest/java/com/yenaly/yenaly_libs/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.yenaly.yenaly_module.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 19 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/SingletonHolder.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs 2 | 3 | /** 4 | * @author Yenaly Liew 5 | * @time 2023/08/29 029 13:58 6 | */ 7 | abstract class SingleArgSingletonHolder(private var constructor: ((A) -> T)?) { 8 | @Volatile 9 | private var instance: T? = null 10 | fun getInstance(arg: A): T = instance ?: synchronized(this) { 11 | instance ?: constructor!!(arg).also { 12 | instance = it 13 | constructor = null 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/base/IViewBinding.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs.base 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.databinding.ViewDataBinding 6 | 7 | interface IViewBinding { 8 | 9 | val binding: DB 10 | 11 | fun getViewBinding(inflater: LayoutInflater, container: ViewGroup?): DB 12 | 13 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/base/YenalyInitializer.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package com.yenaly.yenaly_libs.base 4 | 5 | import android.content.Context 6 | import androidx.annotation.CallSuper 7 | import androidx.startup.Initializer 8 | import com.yenaly.yenaly_libs.utils.applicationContext 9 | 10 | /** 11 | * @ProjectName : YenalyModule 12 | * @Author : Yenaly Liew 13 | * @Time : 2022/04/21 021 14:04 14 | * @Description : Description... 15 | */ 16 | open class YenalyInitializer : Initializer { 17 | 18 | @CallSuper 19 | override fun create(context: Context) { 20 | applicationContext = context 21 | } 22 | 23 | override fun dependencies(): MutableList>> { 24 | return mutableListOf() 25 | } 26 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/base/YenalyViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs.base 2 | 3 | import android.app.Application 4 | import androidx.lifecycle.AndroidViewModel 5 | import com.yenaly.yenaly_libs.utils.unsafeLazy 6 | 7 | /** 8 | * @ProjectName : YenalyModule 9 | * @Author : Yenaly Liew 10 | * @Time : 2022/04/20 020 11:37 11 | * @Description : Description... 12 | */ 13 | open class YenalyViewModel( 14 | @JvmField protected val application: Application 15 | ) : AndroidViewModel(application) { 16 | 17 | var parent: YenalyViewModel? = null 18 | private set 19 | 20 | @Suppress("UNCHECKED_CAST") 21 | fun parent(): YVM? = parent as? YVM 22 | 23 | fun requireParent(): YVM = parent() ?: error("Parent not found") 24 | 25 | inline fun sub() = sub(YVM::class.java) 26 | 27 | fun sub(clazz: Class): Lazy = unsafeLazy { 28 | clazz.getConstructor(Application::class.java).newInstance(application).also { 29 | it.parent = this 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/base/preference/MaterialSwitchPreference.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs.base.preference 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.preference.SwitchPreferenceCompat 6 | import com.yenaly.yenaly_libs.R 7 | 8 | open class MaterialSwitchPreference @JvmOverloads constructor( 9 | context: Context, attrs: AttributeSet? = null, 10 | ) : SwitchPreferenceCompat(context, attrs) { 11 | init { 12 | widgetLayoutResource = R.layout.yenaly_preference_switch_widget 13 | } 14 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/Base64Util.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | @file:JvmName("Base64Util") 3 | 4 | package com.yenaly.yenaly_libs.utils 5 | 6 | import android.util.Base64 7 | 8 | /** 9 | * Base64加密 10 | */ 11 | @JvmName("encodeToString") 12 | fun String.encodeToStringByBase64(flag: Int = Base64.DEFAULT): String { 13 | return Base64.encodeToString(this.toByteArray(), flag) 14 | } 15 | 16 | /** 17 | * Base64解密 18 | */ 19 | @JvmName("decodeFromString") 20 | fun String.decodeFromStringByBase64(flag: Int = Base64.DEFAULT): String { 21 | return String(Base64.decode(this.toByteArray(), flag)) 22 | } 23 | 24 | /** 25 | * Base64解密 26 | */ 27 | @JvmName("decodeFromByteArray") 28 | fun ByteArray.decodeFromByteArrayByBase64(flag: Int = Base64.DEFAULT): ByteArray { 29 | return Base64.decode(this, flag) 30 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/LanguageHelper.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs.utils 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Build 5 | import android.os.LocaleList 6 | import java.util.Locale 7 | 8 | @SuppressLint("ObsoleteSdkInt") 9 | object LanguageHelper { 10 | 11 | val preferredLanguage: Locale 12 | get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 13 | LocaleList.getDefault()[0] 14 | } else { 15 | Locale.getDefault() 16 | } 17 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/LogUtil.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs.utils 2 | 3 | import android.util.Log 4 | import com.yenaly.yenaly_libs.BuildConfig 5 | 6 | fun logFieldsChange(tag: String, oldItem: T, newItem: T) { 7 | if (!BuildConfig.DEBUG) return 8 | 9 | val oldFields = oldItem::class.java.declaredFields 10 | val newFields = newItem::class.java.declaredFields 11 | 12 | for (i in oldFields.indices) { 13 | oldFields[i].isAccessible = true 14 | newFields[i].isAccessible = true 15 | val oldValue = oldFields[i].get(oldItem) 16 | val newValue = newFields[i].get(newItem) 17 | if (oldValue != newValue) { 18 | Log.i(tag, "Field ${oldFields[i].name} changed from $oldValue to $newValue") 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/ToastUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("ToastUtil") 2 | 3 | package com.yenaly.yenaly_libs.utils 4 | 5 | import android.widget.Toast 6 | import androidx.annotation.StringRes 7 | import androidx.fragment.app.Fragment 8 | 9 | fun showShortToast(text: String?) { 10 | Toast.makeText(applicationContext, "$text", Toast.LENGTH_SHORT).show() 11 | } 12 | 13 | fun showLongToast(text: String?) { 14 | Toast.makeText(applicationContext, "$text", Toast.LENGTH_LONG).show() 15 | } 16 | 17 | fun showShortToast(@StringRes text: Int) { 18 | Toast.makeText( 19 | applicationContext, 20 | applicationContext.getString(text), 21 | Toast.LENGTH_SHORT 22 | ).show() 23 | } 24 | 25 | fun showLongToast(@StringRes text: Int) { 26 | Toast.makeText( 27 | applicationContext, 28 | applicationContext.getString(text), 29 | Toast.LENGTH_LONG 30 | ).show() 31 | } 32 | fun Fragment.showShortToast(text: CharSequence) { 33 | Toast.makeText(requireContext(), text, Toast.LENGTH_SHORT).show() 34 | } 35 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/UriUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("UriUtil") 2 | 3 | package com.yenaly.yenaly_libs.utils 4 | 5 | import android.net.Uri 6 | import android.webkit.MimeTypeMap 7 | 8 | inline val Uri.fileExtension get() = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType) 9 | 10 | inline val Uri.mimeType get() = application.contentResolver.getType(this) -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/_GsonUtil.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs.utils 2 | 3 | import com.google.gson.GsonBuilder 4 | import kotlin.reflect.javaType 5 | import kotlin.reflect.typeOf 6 | 7 | val gson by unsafeLazy { 8 | GsonBuilder().create()!! 9 | } 10 | 11 | @OptIn(ExperimentalStdlibApi::class) 12 | inline fun String.fromJson(): T { 13 | return gson.fromJson(this, typeOf().javaType) 14 | } 15 | 16 | fun Any?.toJson(): String { 17 | return gson.toJson(this) 18 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/_LazyUtil.kt: -------------------------------------------------------------------------------- 1 | package com.yenaly.yenaly_libs.utils 2 | 3 | /** 4 | * Android一般用不到[LazyThreadSafetyMode.SYNCHRONIZED]的lazy, 5 | * 使用[LazyThreadSafetyMode.NONE]更合适。 6 | */ 7 | fun unsafeLazy(initializer: () -> T) = lazy(LazyThreadSafetyMode.NONE, initializer) -------------------------------------------------------------------------------- /yenaly_libs/src/main/java/com/yenaly/yenaly_libs/utils/view/EditTextUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("EditTextUtil") 2 | 3 | package com.yenaly.yenaly_libs.utils.view 4 | 5 | import android.view.Window 6 | import android.widget.EditText 7 | import com.yenaly.yenaly_libs.utils.showIme 8 | 9 | /** 10 | * 在EditText上聚焦并显示软键盘 11 | * 12 | * @param window window 13 | */ 14 | fun EditText.showIme(window: Window) = this.let { 15 | it.isFocusable = true 16 | it.isFocusableInTouchMode = true 17 | if (it.hasFocus()) { 18 | window.showIme(true) 19 | } else { 20 | it.requestFocus() 21 | repeat(2) { 22 | window.showIme(true) 23 | } 24 | } 25 | } 26 | 27 | /** 28 | * 在EditText上解除聚焦并隐藏软键盘 29 | * 30 | * @param window window 31 | */ 32 | fun EditText.hideIme(window: Window) = this.let { 33 | it.clearFocus() 34 | window.showIme(false) 35 | } -------------------------------------------------------------------------------- /yenaly_libs/src/main/res/layout/yenaly_activity_crash_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/res/layout/yenaly_activity_settings.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 21 | 22 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/res/layout/yenaly_preference_switch_widget.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 设置 4 | 如果可以,给开发者反馈一下! 5 | 重启软件 6 | 关闭软件 7 | 复制 8 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 18 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /yenaly_libs/src/main/res/xml/http_network_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | --------------------------------------------------------------------------------