├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_request.yml
└── workflows
│ ├── beta.yml
│ ├── pull-req.yml
│ ├── signing-key.jks
│ └── stable.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── debug
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── ani
│ │ └── saikou
│ │ ├── App.kt
│ │ ├── Functions.kt
│ │ ├── MainActivity.kt
│ │ ├── Network.kt
│ │ ├── connections
│ │ ├── UpdateProgress.kt
│ │ ├── anilist
│ │ │ ├── Anilist.kt
│ │ │ ├── AnilistMutations.kt
│ │ │ ├── AnilistQueries.kt
│ │ │ ├── AnilistViewModel.kt
│ │ │ ├── BannerImage.kt
│ │ │ ├── Genre.kt
│ │ │ ├── Login.kt
│ │ │ ├── SearchResults.kt
│ │ │ ├── UrlMedia.kt
│ │ │ └── api
│ │ │ │ ├── Character.kt
│ │ │ │ ├── Data.kt
│ │ │ │ ├── FuzzyDate.kt
│ │ │ │ ├── Media.kt
│ │ │ │ ├── Page.kt
│ │ │ │ ├── Recommendations.kt
│ │ │ │ ├── Staff.kt
│ │ │ │ ├── Studio.kt
│ │ │ │ └── User.kt
│ │ ├── discord
│ │ │ ├── Discord.kt
│ │ │ ├── Login.kt
│ │ │ ├── RPC.kt
│ │ │ └── serializers
│ │ │ │ ├── Activity.kt
│ │ │ │ ├── Identity.kt
│ │ │ │ ├── Presence.kt
│ │ │ │ ├── Res.kt
│ │ │ │ └── User.kt
│ │ └── mal
│ │ │ ├── Login.kt
│ │ │ ├── MAL.kt
│ │ │ └── MALQueries.kt
│ │ ├── download
│ │ └── video
│ │ │ ├── Helper.kt
│ │ │ └── MyDownloadService.kt
│ │ ├── home
│ │ ├── AnimeFragment.kt
│ │ ├── AnimePageAdapter.kt
│ │ ├── HomeFragment.kt
│ │ ├── LoginFragment.kt
│ │ ├── MangaFragment.kt
│ │ ├── MangaPageAdapter.kt
│ │ └── NoInternet.kt
│ │ ├── media
│ │ ├── Author.kt
│ │ ├── AuthorActivity.kt
│ │ ├── CalendarActivity.kt
│ │ ├── Character.kt
│ │ ├── CharacterAdapter.kt
│ │ ├── CharacterDetailsActivity.kt
│ │ ├── CharacterDetailsAdapter.kt
│ │ ├── GenreActivity.kt
│ │ ├── GenreAdapter.kt
│ │ ├── Media.kt
│ │ ├── MediaAdaptor.kt
│ │ ├── MediaDetailsActivity.kt
│ │ ├── MediaDetailsViewModel.kt
│ │ ├── MediaInfoFragment.kt
│ │ ├── MediaListDialogFragment.kt
│ │ ├── MediaListDialogSmallFragment.kt
│ │ ├── OtherDetailsViewModel.kt
│ │ ├── ProgressAdapter.kt
│ │ ├── SearchActivity.kt
│ │ ├── SearchAdapter.kt
│ │ ├── SearchFilterBottomDialog.kt
│ │ ├── Selected.kt
│ │ ├── Source.kt
│ │ ├── SourceAdapter.kt
│ │ ├── SourceSearchDialogFragment.kt
│ │ ├── Studio.kt
│ │ ├── StudioActivity.kt
│ │ ├── TitleAdapter.kt
│ │ ├── anime
│ │ │ ├── Anime.kt
│ │ │ ├── AnimeSourceAdapter.kt
│ │ │ ├── AnimeWatchAdapter.kt
│ │ │ ├── AnimeWatchFragment.kt
│ │ │ ├── Episode.kt
│ │ │ ├── EpisodeAdapters.kt
│ │ │ ├── ExoplayerView.kt
│ │ │ ├── SelectorDialogFragment.kt
│ │ │ ├── SubtitleDialogFragment.kt
│ │ │ └── VideoCache.kt
│ │ ├── manga
│ │ │ ├── Manga.kt
│ │ │ ├── MangaChapter.kt
│ │ │ ├── MangaChapterAdapter.kt
│ │ │ ├── MangaReadAdapter.kt
│ │ │ ├── MangaReadFragment.kt
│ │ │ ├── MangaSourceAdapter.kt
│ │ │ └── mangareader
│ │ │ │ ├── BaseImageAdapter.kt
│ │ │ │ ├── ChapterLoaderDialog.kt
│ │ │ │ ├── DualPageAdapter.kt
│ │ │ │ ├── ImageAdapter.kt
│ │ │ │ ├── MangaReaderActivity.kt
│ │ │ │ ├── PreloadLinearLayoutManager.kt
│ │ │ │ ├── ReaderSettingsDialogFragment.kt
│ │ │ │ ├── RemoveBordersTransformation.kt
│ │ │ │ └── Swipy.kt
│ │ ├── novel
│ │ │ ├── BookDialog.kt
│ │ │ ├── NovelReadAdapter.kt
│ │ │ ├── NovelReadFragment.kt
│ │ │ ├── NovelResponseAdapter.kt
│ │ │ ├── UrlAdapter.kt
│ │ │ └── novelreader
│ │ │ │ ├── NovelReaderActivity.kt
│ │ │ │ └── NovelReaderSettingsDialogFragment.kt
│ │ └── user
│ │ │ ├── ListActivity.kt
│ │ │ ├── ListFragment.kt
│ │ │ ├── ListViewModel.kt
│ │ │ └── ListViewPagerAdapter.kt
│ │ ├── others
│ │ ├── AniSkip.kt
│ │ ├── AppUpdater.kt
│ │ ├── CustomBottomDialog.kt
│ │ ├── Download.kt
│ │ ├── GlideApp.kt
│ │ ├── Idiosyncrasy.kt
│ │ ├── ImageViewDialog.kt
│ │ ├── Jikan.kt
│ │ ├── JsUnpacker.kt
│ │ ├── Kitsu.kt
│ │ ├── MalScraper.kt
│ │ ├── MalSyncBackup.kt
│ │ ├── OutlineTextView.kt
│ │ ├── ResettableTimer.kt
│ │ ├── SpoilerPlugin.kt
│ │ ├── Xpandable.kt
│ │ ├── imagesearch
│ │ │ ├── ImageSearchActivity.kt
│ │ │ ├── ImageSearchResultAdapter.kt
│ │ │ └── ImageSearchViewModel.kt
│ │ └── webview
│ │ │ ├── CloudFlare.kt
│ │ │ └── WebViewBottomDialog.kt
│ │ ├── parsers
│ │ ├── BaseParser.kt
│ │ ├── BaseSources.kt
│ │ ├── anime
│ │ │ ├── AnimeExtractors.kt
│ │ │ ├── AnimeParser.kt
│ │ │ ├── AnimeSources.kt
│ │ │ ├── VideoExtractor.kt
│ │ │ ├── extractors
│ │ │ │ ├── ALions.kt
│ │ │ │ ├── AWish.kt
│ │ │ │ ├── Animeflix.kt
│ │ │ │ ├── BetaPlayer.kt
│ │ │ │ ├── DoodStream.kt
│ │ │ │ ├── FPlayer.kt
│ │ │ │ ├── FileMoon.kt
│ │ │ │ ├── GogoCDN.kt
│ │ │ │ ├── KickAssAnimeV2.kt
│ │ │ │ ├── Maverickki.kt
│ │ │ │ ├── MixDrop.kt
│ │ │ │ ├── Mp4Upload.kt
│ │ │ │ ├── OkRu.kt
│ │ │ │ ├── PinkBird.kt
│ │ │ │ ├── RapidCloud.kt
│ │ │ │ ├── StreamSB.kt
│ │ │ │ ├── StreamTape.kt
│ │ │ │ └── VidStreaming.kt
│ │ │ └── sources
│ │ │ │ ├── AllAnime.kt
│ │ │ │ ├── AniWave.kt
│ │ │ │ ├── AnimeDao.kt
│ │ │ │ ├── AnimeDummy.kt
│ │ │ │ ├── AnimePahe.kt
│ │ │ │ ├── Animeflix.kt
│ │ │ │ ├── Animension.kt
│ │ │ │ ├── Gogo.kt
│ │ │ │ ├── Haho.kt
│ │ │ │ ├── HentaiFF.kt
│ │ │ │ ├── HentaiMama.kt
│ │ │ │ ├── HentaiStream.kt
│ │ │ │ ├── Kaido.kt
│ │ │ │ ├── KickAssAnime.kt
│ │ │ │ └── SFlix.kt
│ │ ├── manga
│ │ │ ├── MangaParser.kt
│ │ │ ├── MangaSources.kt
│ │ │ └── sources
│ │ │ │ ├── AllAnime.kt
│ │ │ │ ├── AsurScans.kt
│ │ │ │ ├── ComickFun.kt
│ │ │ │ ├── Manga4Life.kt
│ │ │ │ ├── MangaBuddy.kt
│ │ │ │ ├── MangaDex.kt
│ │ │ │ ├── MangaDummy.kt
│ │ │ │ ├── MangaHub.kt
│ │ │ │ ├── MangaKakalot.kt
│ │ │ │ ├── MangaKatana.kt
│ │ │ │ ├── MangaPill.kt
│ │ │ │ ├── MangaRead.kt
│ │ │ │ ├── Manhwa18.kt
│ │ │ │ ├── MmScans.kt
│ │ │ │ ├── NineHentai.kt
│ │ │ │ └── Toonily.kt
│ │ └── novel
│ │ │ ├── NovelParser.kt
│ │ │ ├── NovelSources.kt
│ │ │ └── sources
│ │ │ └── NovelDummy.kt
│ │ ├── settings
│ │ ├── CurrentNovelReaderSettings.kt
│ │ ├── CurrentReaderSettings.kt
│ │ ├── Developer.kt
│ │ ├── DevelopersAdapter.kt
│ │ ├── DevelopersDialogFragment.kt
│ │ ├── FAQActivity.kt
│ │ ├── FAQAdapter.kt
│ │ ├── ForksDialogFragment.kt
│ │ ├── NovelReaderSettings.kt
│ │ ├── PlayerSettings.kt
│ │ ├── PlayerSettingsActivity.kt
│ │ ├── ReaderSettings.kt
│ │ ├── ReaderSettingsActivity.kt
│ │ ├── SettingsActivity.kt
│ │ ├── SettingsDialogFragment.kt
│ │ ├── UserInterfaceSettings.kt
│ │ └── UserInterfaceSettingsActivity.kt
│ │ └── subcriptions
│ │ ├── AlarmReceiver.kt
│ │ ├── Notifications.kt
│ │ ├── Subscription.kt
│ │ ├── SubscriptionHelper.kt
│ │ └── SubscriptionWorker.kt
│ └── res
│ ├── anim
│ └── over_shoot.xml
│ ├── color
│ ├── button_switch_track.xml
│ ├── tab_layout_icon.xml
│ └── tab_layout_text.xml
│ ├── drawable
│ ├── anim_pause_to_play.xml
│ ├── anim_play_to_pause.xml
│ ├── anim_rewind.xml
│ ├── anim_skip.xml
│ ├── anim_splash.xml
│ ├── baseline_invert_colors_24.xml
│ ├── bottom_nav.xml
│ ├── buymecofee.png
│ ├── control_background_40dp.xml
│ ├── ic_add.xml
│ ├── ic_anilist.xml
│ ├── ic_baseline_screen_lock_portrait_24.xml
│ ├── ic_discord.xml
│ ├── ic_github.xml
│ ├── ic_launcher_background.xml
│ ├── ic_launcher_foreground.xml
│ ├── ic_minus.xml
│ ├── ic_myanimelist.xml
│ ├── ic_page_numbering.xml
│ ├── ic_round_accessible_forward_24.xml
│ ├── ic_round_add_circle_24.xml
│ ├── ic_round_add_circle_outline_24.xml
│ ├── ic_round_alpha_t_box_24.xml
│ ├── ic_round_amp_stories_24.xml
│ ├── ic_round_animation_24.xml
│ ├── ic_round_arrow_back_ios_new_24.xml
│ ├── ic_round_arrow_drop_down_24.xml
│ ├── ic_round_art_track_24.xml
│ ├── ic_round_audiotrack_24.xml
│ ├── ic_round_auto_awesome_24.xml
│ ├── ic_round_brightness_4_24.xml
│ ├── ic_round_brightness_auto_24.xml
│ ├── ic_round_brightness_high_24.xml
│ ├── ic_round_brightness_medium_24.xml
│ ├── ic_round_calendar_today_24.xml
│ ├── ic_round_cast_24.xml
│ ├── ic_round_close_24.xml
│ ├── ic_round_collections_bookmark_24.xml
│ ├── ic_round_color_24.xml
│ ├── ic_round_date_range_24.xml
│ ├── ic_round_dns_24.xml
│ ├── ic_round_download_24.xml
│ ├── ic_round_edit_note_24.xml
│ ├── ic_round_fast_forward_24.xml
│ ├── ic_round_fast_rewind_24.xml
│ ├── ic_round_favorite_24.xml
│ ├── ic_round_favorite_border_24.xml
│ ├── ic_round_filter_alt_24.xml
│ ├── ic_round_font_size_24.xml
│ ├── ic_round_format_text_24.xml
│ ├── ic_round_fullscreen_24.xml
│ ├── ic_round_grid_view_24.xml
│ ├── ic_round_heart_broken_24.xml
│ ├── ic_round_help_24.xml
│ ├── ic_round_high_quality_24.xml
│ ├── ic_round_home_24.xml
│ ├── ic_round_image_search_24.xml
│ ├── ic_round_import_contacts_24.xml
│ ├── ic_round_info_24.xml
│ ├── ic_round_lock_24.xml
│ ├── ic_round_lock_open_24.xml
│ ├── ic_round_menu_book_24.xml
│ ├── ic_round_movie_filter_24.xml
│ ├── ic_round_new_releases_24.xml
│ ├── ic_round_notifications_active_24.xml
│ ├── ic_round_notifications_none_24.xml
│ ├── ic_round_pause_24.xml
│ ├── ic_round_person_24.xml
│ ├── ic_round_photo_size_select_actual_24.xml
│ ├── ic_round_picture_in_picture_alt_24.xml
│ ├── ic_round_play_arrow_24.xml
│ ├── ic_round_play_circle_24.xml
│ ├── ic_round_play_disabled_24.xml
│ ├── ic_round_playlist_add_24.xml
│ ├── ic_round_playlist_play_24.xml
│ ├── ic_round_reader_settings.xml
│ ├── ic_round_refresh_24.xml
│ ├── ic_round_remove_red_eye_24.xml
│ ├── ic_round_restaurant_24.xml
│ ├── ic_round_screen_rotation_24.xml
│ ├── ic_round_screen_rotation_alt_24.xml
│ ├── ic_round_sd_card_24.xml
│ ├── ic_round_search_24.xml
│ ├── ic_round_settings_24.xml
│ ├── ic_round_share_24.xml
│ ├── ic_round_skip_next_24.xml
│ ├── ic_round_skip_previous_24.xml
│ ├── ic_round_slow_motion_video_24.xml
│ ├── ic_round_smart_button_24.xml
│ ├── ic_round_sort_24.xml
│ ├── ic_round_source_24.xml
│ ├── ic_round_space_bar_24.xml
│ ├── ic_round_star_24.xml
│ ├── ic_round_straighten_24.xml
│ ├── ic_round_subtitles_24.xml
│ ├── ic_round_swipe_down_alt_24.xml
│ ├── ic_round_swipe_up_alt_24.xml
│ ├── ic_round_swipe_vertical_24.xml
│ ├── ic_round_sync_24.xml
│ ├── ic_round_touch_app_24.xml
│ ├── ic_round_translate_variant_24.xml
│ ├── ic_round_video_library_24.xml
│ ├── ic_round_video_settings_24.xml
│ ├── ic_round_view_array_24.xml
│ ├── ic_round_view_column_24.xml
│ ├── ic_round_view_comfy_24.xml
│ ├── ic_round_view_list_24.xml
│ ├── ic_round_volume_up_24.xml
│ ├── ic_skip.xml
│ ├── ic_telegram.xml
│ ├── ic_upi_icon.xml
│ ├── item_ongoing.xml
│ ├── item_score.xml
│ ├── item_type.xml
│ ├── item_user_score.xml
│ ├── kofi_s_tag_dark.png
│ ├── linear_gradient_bg.xml
│ ├── linear_gradient_black.xml
│ ├── linear_gradient_black_horizontal.xml
│ ├── linear_gradient_nav.xml
│ ├── mono.xml
│ ├── monochrome.xml
│ ├── round_corner.xml
│ ├── rounded_top_nav.xml
│ ├── shape_corner_16dp.xml
│ ├── spinner_icon.xml
│ ├── spinner_icon_manga.xml
│ └── ui_bg.xml
│ ├── font
│ ├── poppins.ttf
│ ├── poppins_bold.ttf
│ ├── poppins_family.xml
│ ├── poppins_semi_bold.ttf
│ └── poppins_thin.ttf
│ ├── layout-land
│ └── activity_media.xml
│ ├── layout
│ ├── activity_author.xml
│ ├── activity_character.xml
│ ├── activity_discord.xml
│ ├── activity_exoplayer.xml
│ ├── activity_faq.xml
│ ├── activity_genre.xml
│ ├── activity_image_search.xml
│ ├── activity_list.xml
│ ├── activity_main.xml
│ ├── activity_manga_reader.xml
│ ├── activity_media.xml
│ ├── activity_no_internet.xml
│ ├── activity_novel_reader.xml
│ ├── activity_player_settings.xml
│ ├── activity_reader_settings.xml
│ ├── activity_search.xml
│ ├── activity_settings.xml
│ ├── activity_studio.xml
│ ├── activity_user_interface_settings.xml
│ ├── bottom_sheet_book.xml
│ ├── bottom_sheet_current_novel_reader_settings.xml
│ ├── bottom_sheet_current_reader_settings.xml
│ ├── bottom_sheet_custom.xml
│ ├── bottom_sheet_developers.xml
│ ├── bottom_sheet_image.xml
│ ├── bottom_sheet_media_list.xml
│ ├── bottom_sheet_media_list_small.xml
│ ├── bottom_sheet_search_filter.xml
│ ├── bottom_sheet_selector.xml
│ ├── bottom_sheet_settings.xml
│ ├── bottom_sheet_source_search.xml
│ ├── bottom_sheet_subtitles.xml
│ ├── bottom_sheet_webview.xml
│ ├── exo_player_control_view.xml
│ ├── exo_player_view.xml
│ ├── fragment_anime.xml
│ ├── fragment_anime_watch.xml
│ ├── fragment_home.xml
│ ├── fragment_list.xml
│ ├── fragment_login.xml
│ ├── fragment_manga.xml
│ ├── fragment_media_info.xml
│ ├── item_anime_page.xml
│ ├── item_anime_watch.xml
│ ├── item_chapter_list.xml
│ ├── item_character.xml
│ ├── item_character_details.xml
│ ├── item_chip.xml
│ ├── item_count_down.xml
│ ├── item_developer.xml
│ ├── item_dropdown.xml
│ ├── item_dual_page.xml
│ ├── item_episode_compact.xml
│ ├── item_episode_grid.xml
│ ├── item_episode_list.xml
│ ├── item_episodes_recyclerview.xml
│ ├── item_genre.xml
│ ├── item_image.xml
│ ├── item_manga_page.xml
│ ├── item_media_compact.xml
│ ├── item_media_large.xml
│ ├── item_media_page.xml
│ ├── item_media_page_small.xml
│ ├── item_novel_header.xml
│ ├── item_novel_response.xml
│ ├── item_progressbar.xml
│ ├── item_quels.xml
│ ├── item_question.xml
│ ├── item_recyclerview.xml
│ ├── item_search_by_image.xml
│ ├── item_search_header.xml
│ ├── item_seekbar_dialog.xml
│ ├── item_stream.xml
│ ├── item_subtitle_text.xml
│ ├── item_title.xml
│ ├── item_title_chipgroup.xml
│ ├── item_title_recycler.xml
│ ├── item_title_text.xml
│ ├── item_title_trailer.xml
│ ├── item_url.xml
│ └── splash_screen.xml
│ ├── menu
│ ├── anime_menu_detail.xml
│ ├── bottom_navbar_menu.xml
│ ├── list_sort_menu.xml
│ ├── manga_menu_detail.xml
│ └── menu_media.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── values-night
│ ├── colors.xml
│ └── themes.xml
│ ├── values
│ ├── attr.xml
│ ├── colors.xml
│ ├── font_certs.xml
│ ├── preloaded_fonts.xml
│ ├── strings.xml
│ ├── style.xml
│ └── themes.xml
│ └── xml
│ └── provider_paths.xml
├── beta.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── stable.md
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: brahmkshatriya
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Discord Server
4 | url: https://discord.gg/2T7TunuwFZ
5 | about: Join our Discord server for support and updates.
6 | - name: Telegram group
7 | url: https://t.me/saikou_discussion
8 | about: Join our Telegram discussion group for support and updates.
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature Request
2 | description: Suggest a feature for Saikou
3 | labels: enhancement
4 | body:
5 |
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Please make sure that you have read the entire README.
10 | Especially the [Planned Stuff](https://github.com/saikou-app/saikou#planned-stuff) and [Rejected Stuff](https://github.com/saikou-app/saikou#rejected-stuff).
11 |
12 | - type: input
13 | attributes:
14 | label: Summary
15 | description: A short summary of what your feature request is.
16 | validations:
17 | required: true
18 |
19 | - type: textarea
20 | attributes:
21 | label: The Problem
22 | description: >
23 | What problem is your feature trying to solve?
24 | What becomes easier or possible when this feature is implemented?
25 | validations:
26 | required: true
27 |
28 | - type: textarea
29 | attributes:
30 | label: The Ideal Solution
31 | description: >
32 | What is your ideal solution to the problem?
33 | What would you like this feature to do?
34 | validations:
35 | required: true
36 |
37 | - type: textarea
38 | attributes:
39 | label: The Current Solution
40 | description: What is the current solution to the problem, if any?
41 | validations:
42 | required: false
43 |
44 | - type: textarea
45 | attributes:
46 | label: Additional Context
47 | description: If there is anything else to say, please do so here.
48 |
49 |
--------------------------------------------------------------------------------
/.github/workflows/pull-req.yml:
--------------------------------------------------------------------------------
1 | name: PR Test Builds
2 |
3 | on:
4 | pull_request:
5 | branches: [ main ]
6 | jobs:
7 | build:
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v3
12 |
13 | - name: set up JDK 17
14 | uses: actions/setup-java@v3
15 | with:
16 | java-version: '17'
17 | distribution: 'temurin'
18 | cache: gradle
19 |
20 | - name: Grant execute permission for gradlew
21 | run: chmod +x gradlew
22 | - name: Build with Gradle
23 | run: ./gradlew assembleDebug
24 | shell: bash
25 |
26 | - name: Upload a Build Artifact
27 | uses: actions/upload-artifact@v3.0.0
28 | with:
29 | path: "app/build/outputs/apk/debug/app-debug.apk"
30 |
--------------------------------------------------------------------------------
/.github/workflows/signing-key.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/.github/workflows/signing-key.jks
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | .idea
4 | build
5 | local.properties
6 | .DS_Store
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /debug
3 | /debug/output-metadata.json
4 | /release
--------------------------------------------------------------------------------
/app/src/debug/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Saikou β
4 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/UpdateProgress.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections
2 |
3 | import ani.saikou.R
4 | import ani.saikou.Refresh
5 | import ani.saikou.connections.anilist.Anilist
6 | import ani.saikou.connections.mal.MAL
7 | import ani.saikou.currContext
8 | import ani.saikou.media.Media
9 | import ani.saikou.toast
10 | import kotlinx.coroutines.CoroutineScope
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.launch
13 | import kotlin.math.roundToInt
14 |
15 | fun updateProgress(media: Media, number: String) {
16 | if (Anilist.userid != null) {
17 | CoroutineScope(Dispatchers.IO).launch {
18 | val a = number.toFloatOrNull()?.roundToInt()
19 | if (a != media.userProgress) {
20 | Anilist.mutation.editList(
21 | media.id,
22 | a,
23 | status = if (media.userStatus == "REPEATING") media.userStatus else "CURRENT"
24 | )
25 | MAL.query.editList(
26 | media.idMAL,
27 | media.anime != null,
28 | a, null,
29 | if (media.userStatus == "REPEATING") media.userStatus!! else "CURRENT"
30 | )
31 | toast(currContext()?.getString(R.string.setting_progress, a))
32 | }
33 | media.userProgress = a
34 | Refresh.all()
35 | }
36 | } else {
37 | toast(currContext()?.getString(R.string.login_anilist_account))
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/anilist/BannerImage.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.anilist
2 |
3 | import java.io.Serializable
4 |
5 | data class BannerImage(
6 | val url: String?,
7 | var time: Long,
8 | ) : Serializable {
9 | fun checkTime(): Boolean {
10 | return (System.currentTimeMillis() - time) >= (1000 * 60 * 60 * 6)
11 | }
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/anilist/Genre.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.anilist
2 |
3 | import java.io.Serializable
4 |
5 | data class Genre(
6 | val name: String,
7 | var id: Int,
8 | var thumbnail: String,
9 | var time: Long,
10 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/anilist/Login.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.anilist
2 |
3 | import android.content.Context
4 | import android.net.Uri
5 | import android.os.Bundle
6 | import androidx.appcompat.app.AppCompatActivity
7 | import ani.saikou.logError
8 | import ani.saikou.logger
9 | import ani.saikou.startMainActivity
10 |
11 | class Login : AppCompatActivity() {
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | val data: Uri? = intent?.data
15 | logger(data.toString())
16 | try {
17 | Anilist.token = Regex("""(?<=access_token=).+(?=&token_type)""").find(data.toString())!!.value
18 | val filename = "anilistToken"
19 | this.openFileOutput(filename, Context.MODE_PRIVATE).use {
20 | it.write(Anilist.token!!.toByteArray())
21 | }
22 | } catch (e: Exception) {
23 | logError(e)
24 | }
25 | startMainActivity(this)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/anilist/UrlMedia.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.anilist
2 |
3 | import android.app.Activity
4 | import android.net.Uri
5 | import android.os.Bundle
6 | import androidx.core.os.bundleOf
7 | import ani.saikou.loadMedia
8 | import ani.saikou.startMainActivity
9 |
10 | class UrlMedia : Activity() {
11 | override fun onCreate(savedInstanceState: Bundle?) {
12 | super.onCreate(savedInstanceState)
13 | var id: Int? = intent?.extras?.getInt("media", 0) ?: 0
14 | var isMAL = false
15 | var continueMedia = true
16 | if (id == 0) {
17 | continueMedia = false
18 | val data: Uri? = intent?.data
19 | isMAL = data?.host != "anilist.co"
20 | id = data?.pathSegments?.getOrNull(1)?.toIntOrNull()
21 | } else loadMedia = id
22 | startMainActivity(this, bundleOf("mediaId" to id, "mal" to isMAL, "continue" to continueMedia))
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/anilist/api/Recommendations.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.anilist.api
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | @Serializable
6 | data class Recommendation(
7 | // The id of the recommendation
8 | @SerialName("id") var id: Int?,
9 |
10 | // Users rating of the recommendation
11 | @SerialName("rating") var rating: Int?,
12 |
13 | // The rating of the recommendation by currently authenticated user
14 | // @SerialName("userRating") var userRating: RecommendationRating?,
15 |
16 | // The media the recommendation is from
17 | @SerialName("media") var media: Media?,
18 |
19 | // The recommended media
20 | @SerialName("mediaRecommendation") var mediaRecommendation: Media?,
21 |
22 | // The user that first created the recommendation
23 | @SerialName("user") var user: User?,
24 | )
25 | @Serializable
26 | data class RecommendationConnection(
27 | //@SerialName("edges") var edges: List?,
28 |
29 | @SerialName("nodes") var nodes: List?,
30 |
31 | // The pagination information
32 | //@SerialName("pageInfo") var pageInfo: PageInfo?,
33 |
34 | )
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/anilist/api/Studio.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.anilist.api
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class Studio(
8 | // The id of the studio
9 | @SerialName("id") var id: Int,
10 |
11 | // The name of the studio
12 | // Originally non-nullable, needs to be nullable due to it not being always queried
13 | @SerialName("name") var name: String?,
14 |
15 | // If the studio is an animation studio or a different kind of company
16 | @SerialName("isAnimationStudio") var isAnimationStudio: Boolean?,
17 |
18 | // The media the studio has worked on
19 | @SerialName("media") var media: MediaConnection?,
20 |
21 | // The url for the studio page on the AniList website
22 | @SerialName("siteUrl") var siteUrl: String?,
23 |
24 | // If the studio is marked as favourite by the currently authenticated user
25 | @SerialName("isFavourite") var isFavourite: Boolean?,
26 |
27 | // The amount of user's who have favourited the studio
28 | @SerialName("favourites") var favourites: Int?,
29 | )
30 |
31 | @Serializable
32 | data class StudioConnection(
33 | //@SerialName("edges") var edges: List?,
34 |
35 | @SerialName("nodes") var nodes: List?,
36 |
37 | // The pagination information
38 | //@SerialName("pageInfo") var pageInfo: PageInfo?,
39 | )
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/discord/serializers/Activity.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.discord.serializers
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | @Serializable
6 | data class Activity (
7 | @SerialName("application_id")
8 | val applicationId: String? = null,
9 | val name: String? = null,
10 | val details: String? = null,
11 | val state: String? = null,
12 | val type: Int? = null,
13 | val timestamps: Timestamps? = null,
14 | val assets: Assets? = null,
15 | val buttons: List? = null,
16 | val metadata: Metadata? = null
17 | ) {
18 | @Serializable
19 | data class Assets(
20 | @SerialName("large_image")
21 | val largeImage: String? = null,
22 |
23 | @SerialName("large_text")
24 | val largeText: String? = null,
25 |
26 | @SerialName("small_image")
27 | val smallImage: String? = null,
28 |
29 | @SerialName("small_text")
30 | val smallText: String? = null
31 | )
32 |
33 | @Serializable
34 | data class Metadata(
35 | @SerialName("button_urls")
36 | val buttonUrls: List
37 | )
38 |
39 | @Serializable
40 | data class Timestamps(
41 | val start: Long? = null,
42 | val stop: Long? = null
43 | )
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/discord/serializers/Identity.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.discord.serializers
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class Identity(
8 | val token: String,
9 | val properties: Properties,
10 | val compress: Boolean,
11 | val intents: Long
12 | ) {
13 |
14 | @Serializable
15 | data class Response (
16 | val op: Long,
17 | val d: Identity
18 | )
19 |
20 | @Serializable
21 | data class Properties (
22 | @SerialName("\$os")
23 | val os: String,
24 |
25 | @SerialName("\$browser")
26 | val browser: String,
27 |
28 | @SerialName("\$device")
29 | val device: String
30 | )
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/discord/serializers/Presence.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.discord.serializers
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class Presence (
7 | val activities: List = listOf(),
8 | val afk: Boolean = true,
9 | val since: Long? = null,
10 | val status: String? = null
11 | ){
12 | @Serializable
13 | data class Response (
14 | val op: Long,
15 | val d: Presence
16 | )
17 | }
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/connections/discord/serializers/Res.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.connections.discord.serializers
2 |
3 | import kotlinx.serialization.Serializable
4 | import kotlinx.serialization.json.JsonElement
5 |
6 | @Serializable
7 | data class Res(
8 | val t: String?,
9 | val s: Int?,
10 | val op: Int,
11 | val d: JsonElement
12 | )
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/download/video/MyDownloadService.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.download.video
2 |
3 | import android.app.Notification
4 | import androidx.media3.common.util.UnstableApi
5 | import androidx.media3.exoplayer.offline.Download
6 | import androidx.media3.exoplayer.offline.DownloadManager
7 | import androidx.media3.exoplayer.offline.DownloadNotificationHelper
8 | import androidx.media3.exoplayer.offline.DownloadService
9 | import androidx.media3.exoplayer.scheduler.PlatformScheduler
10 | import androidx.media3.exoplayer.scheduler.Scheduler
11 | import ani.saikou.R
12 |
13 | @UnstableApi
14 | class MyDownloadService : DownloadService(1, 1, "download_service", R.string.downloads, 0) {
15 | companion object {
16 | private const val JOB_ID = 1
17 | private const val FOREGROUND_NOTIFICATION_ID = 1
18 | }
19 |
20 | override fun getDownloadManager(): DownloadManager = Helper.downloadManager(this)
21 |
22 | override fun getScheduler(): Scheduler = PlatformScheduler(this, JOB_ID)
23 |
24 | override fun getForegroundNotification(downloads: MutableList, notMetRequirements: Int): Notification =
25 | DownloadNotificationHelper(this, "download_service").buildProgressNotification(
26 | this,
27 | R.drawable.monochrome,
28 | null,
29 | null,
30 | downloads,
31 | notMetRequirements
32 | )
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/home/LoginFragment.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.home
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.fragment.app.Fragment
8 | import ani.saikou.R
9 | import ani.saikou.connections.anilist.Anilist
10 | import ani.saikou.databinding.FragmentLoginBinding
11 | import ani.saikou.openLinkInBrowser
12 |
13 | class LoginFragment : Fragment() {
14 |
15 | private var _binding: FragmentLoginBinding? = null
16 | private val binding get() = _binding!!
17 |
18 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
19 | _binding = FragmentLoginBinding.inflate(layoutInflater, container, false)
20 | return binding.root
21 | }
22 |
23 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
24 | binding.loginButton.setOnClickListener { Anilist.loginIntent(requireActivity()) }
25 | binding.loginDiscord.setOnClickListener { openLinkInBrowser(getString(R.string.discord)) }
26 | binding.loginTelegram.setOnClickListener { openLinkInBrowser(getString(R.string.telegram)) }
27 | binding.loginGithub.setOnClickListener { openLinkInBrowser(getString(R.string.github)) }
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/home/NoInternet.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.home
2 |
3 | import android.os.Bundle
4 | import android.view.ViewGroup
5 | import androidx.appcompat.app.AppCompatActivity
6 | import androidx.core.view.updateLayoutParams
7 | import ani.saikou.databinding.ActivityNoInternetBinding
8 | import ani.saikou.isOnline
9 | import ani.saikou.navBarHeight
10 | import ani.saikou.startMainActivity
11 | import ani.saikou.statusBarHeight
12 |
13 | class NoInternet : AppCompatActivity() {
14 | override fun onCreate(savedInstanceState: Bundle?) {
15 | super.onCreate(savedInstanceState)
16 |
17 | val binding = ActivityNoInternetBinding.inflate(layoutInflater)
18 | setContentView(binding.root)
19 |
20 | binding.refreshContainer.updateLayoutParams {
21 | topMargin = statusBarHeight
22 | bottomMargin = navBarHeight
23 | }
24 | binding.refreshButton.setOnClickListener {
25 | if (isOnline(this)) {
26 | startMainActivity(this)
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/Author.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media
2 |
3 | import java.io.Serializable
4 |
5 | data class Author(
6 | val id: String,
7 | val name: String,
8 | var yearMedia: MutableMap>? = null
9 | ) : Serializable
10 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/Character.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media
2 |
3 | import ani.saikou.connections.anilist.api.FuzzyDate
4 | import java.io.Serializable
5 |
6 | data class Character(
7 | val id: Int,
8 | val name: String?,
9 | val image: String?,
10 | val banner: String?,
11 | val role: String,
12 |
13 | var description: String? = null,
14 | var age: String? = null,
15 | var gender: String? = null,
16 | var dateOfBirth: FuzzyDate? = null,
17 | var roles: ArrayList? = null
18 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/Selected.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media
2 |
3 | import java.io.Serializable
4 |
5 | data class Selected(
6 | var window: Int = 0,
7 | var recyclerStyle: Int? = null,
8 | var recyclerReversed: Boolean = false,
9 | var chip: Int = 0,
10 | var source: Int = 0,
11 | var preferDub: Boolean = false,
12 | var server: String? = null,
13 | var video: Int = 0,
14 | var latest: Float = 0f,
15 | ) : Serializable
16 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/Source.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media
2 |
3 | import java.io.Serializable
4 |
5 | data class Source(
6 | val link: String,
7 | val name: String,
8 | val cover: String,
9 | val headers: MutableMap? = null
10 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/Studio.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media
2 |
3 | import java.io.Serializable
4 |
5 | data class Studio(
6 | val id: String,
7 | val name: String,
8 | var yearMedia: MutableMap>? = null
9 | ) : Serializable
10 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/TitleAdapter.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media
2 |
3 | import android.view.LayoutInflater
4 | import android.view.ViewGroup
5 | import androidx.recyclerview.widget.RecyclerView
6 | import ani.saikou.databinding.ItemTitleBinding
7 |
8 | class TitleAdapter(private val text: String) : RecyclerView.Adapter() {
9 | inner class TitleViewHolder(val binding: ItemTitleBinding) : RecyclerView.ViewHolder(binding.root)
10 |
11 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TitleViewHolder {
12 | val binding = ItemTitleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
13 | return TitleViewHolder(binding)
14 | }
15 |
16 | override fun onBindViewHolder(holder: TitleViewHolder, position: Int) {
17 | holder.binding.itemTitle.text = text
18 | }
19 |
20 | override fun getItemCount(): Int = 1
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/anime/Anime.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.anime
2 |
3 | import ani.saikou.media.Author
4 | import ani.saikou.media.Studio
5 | import java.io.Serializable
6 |
7 | data class Anime(
8 | var totalEpisodes: Int? = null,
9 |
10 | var episodeDuration: Int? = null,
11 | var season: String? = null,
12 | var seasonYear: Int? = null,
13 |
14 | var op: ArrayList = arrayListOf(),
15 | var ed: ArrayList = arrayListOf(),
16 |
17 | var mainStudio: Studio? = null,
18 | var author: Author?=null,
19 |
20 | var youtube: String? = null,
21 | var nextAiringEpisode: Int? = null,
22 | var nextAiringEpisodeTime: Long? = null,
23 |
24 | var selectedEpisode: String? = null,
25 | var episodes: MutableMap? = null,
26 | var slug: String? = null,
27 | var kitsuEpisodes: Map? = null,
28 | var fillerEpisodes: Map? = null,
29 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/anime/AnimeSourceAdapter.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.anime
2 |
3 | import ani.saikou.media.MediaDetailsViewModel
4 | import ani.saikou.media.SourceAdapter
5 | import ani.saikou.media.SourceSearchDialogFragment
6 | import ani.saikou.parsers.ShowResponse
7 | import kotlinx.coroutines.CoroutineScope
8 |
9 | class AnimeSourceAdapter(
10 | sources: List,
11 | val model: MediaDetailsViewModel,
12 | val i: Int,
13 | val id: Int,
14 | fragment: SourceSearchDialogFragment,
15 | scope: CoroutineScope
16 | ) : SourceAdapter(sources, fragment, scope) {
17 |
18 | override suspend fun onItemClick(source: ShowResponse) {
19 | model.overrideEpisodes(i, source, id)
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/anime/Episode.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.anime
2 |
3 | import ani.saikou.FileUrl
4 | import ani.saikou.parsers.anime.VideoExtractor
5 | import java.io.Serializable
6 |
7 | data class Episode(
8 | val number: String,
9 | var link: String? = null,
10 | var title: String? = null,
11 | var desc: String? = null,
12 | var thumb: FileUrl? = null,
13 | var filler: Boolean = false,
14 | var selectedExtractor: String? = null,
15 | var selectedVideo: Int = 0,
16 | var selectedSubtitle: Int? = -1,
17 | var extractors: MutableList?=null,
18 | @Transient var extractorCallback: ((VideoExtractor) -> Unit)?=null,
19 | var allStreams: Boolean = false,
20 | var watched: Long? = null,
21 | var maxLength: Long? = null,
22 | val extra: Map?=null,
23 | ) : Serializable
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/anime/VideoCache.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.anime
2 |
3 | import android.content.Context
4 | import androidx.media3.common.util.UnstableApi
5 | import androidx.media3.database.StandaloneDatabaseProvider
6 | import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
7 | import androidx.media3.datasource.cache.SimpleCache
8 | import java.io.File
9 |
10 | @UnstableApi
11 | object VideoCache {
12 | private var simpleCache: SimpleCache? = null
13 | fun getInstance(context: Context): SimpleCache {
14 | val databaseProvider = StandaloneDatabaseProvider(context)
15 | if (simpleCache == null)
16 | simpleCache = SimpleCache(
17 | File(context.cacheDir, "exoplayer").also { it.deleteOnExit() }, // Ensures always fresh file
18 | LeastRecentlyUsedCacheEvictor(300L * 1024L * 1024L),
19 | databaseProvider
20 | )
21 | return simpleCache as SimpleCache
22 | }
23 |
24 | fun release() {
25 | simpleCache?.release()
26 | simpleCache = null
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/manga/Manga.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.manga
2 |
3 | import ani.saikou.media.Author
4 | import java.io.Serializable
5 |
6 | data class Manga(
7 | var totalChapters: Int? = null,
8 | var selectedChapter: String? = null,
9 | var chapters: MutableMap? = null,
10 | var slug: String? = null,
11 | var author: Author?=null,
12 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/manga/MangaChapter.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.manga
2 |
3 | import ani.saikou.parsers.manga.MangaChapter
4 | import ani.saikou.parsers.manga.MangaImage
5 | import java.io.Serializable
6 | import kotlin.math.floor
7 |
8 | data class MangaChapter(
9 | val number: String,
10 | var link: String,
11 | var title: String? = null,
12 | var description: String? = null,
13 | ) : Serializable {
14 | constructor(chapter: MangaChapter) : this(chapter.number, chapter.link, chapter.title, chapter.description)
15 |
16 | private val images = mutableListOf()
17 | fun images(): List = images
18 | fun addImages(image: List) {
19 | if (images.isNotEmpty()) return
20 | image.forEach { images.add(it) }
21 | (0..floor((images.size.toFloat() - 1f) / 2).toInt()).forEach {
22 | val i = it * 2
23 | dualPages.add(images[i] to images.getOrNull(i + 1))
24 | }
25 | }
26 |
27 | private val dualPages = mutableListOf>()
28 | fun dualPages(): List> = dualPages
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/manga/MangaSourceAdapter.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.manga
2 |
3 | import ani.saikou.media.MediaDetailsViewModel
4 | import ani.saikou.media.SourceAdapter
5 | import ani.saikou.media.SourceSearchDialogFragment
6 | import ani.saikou.parsers.ShowResponse
7 | import kotlinx.coroutines.CoroutineScope
8 |
9 | class MangaSourceAdapter(
10 | sources: List,
11 | val model: MediaDetailsViewModel,
12 | val i: Int,
13 | val id: Int,
14 | fragment: SourceSearchDialogFragment,
15 | scope: CoroutineScope
16 | ) : SourceAdapter(sources, fragment, scope) {
17 | override suspend fun onItemClick(source: ShowResponse) {
18 | model.overrideMangaChapters(i, source, id)
19 | }
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/user/ListViewModel.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.user
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import androidx.lifecycle.ViewModel
6 | import ani.saikou.connections.anilist.Anilist
7 | import ani.saikou.loadData
8 | import ani.saikou.media.Media
9 | import ani.saikou.tryWithSuspend
10 |
11 | class ListViewModel : ViewModel() {
12 | var grid = MutableLiveData(loadData("listGrid") ?: true)
13 |
14 | private val lists = MutableLiveData>>()
15 | fun getLists(): LiveData>> = lists
16 | suspend fun loadLists(anime: Boolean, userId: Int, sortOrder: String? = null) {
17 | tryWithSuspend {
18 | lists.postValue(Anilist.query.getMediaLists(anime, userId, sortOrder))
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/media/user/ListViewPagerAdapter.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.media.user
2 |
3 | import androidx.fragment.app.Fragment
4 | import androidx.fragment.app.FragmentActivity
5 | import androidx.viewpager2.adapter.FragmentStateAdapter
6 |
7 | class ListViewPagerAdapter(private val size: Int, private val calendar: Boolean, fragment: FragmentActivity) :
8 | FragmentStateAdapter(fragment) {
9 | override fun getItemCount(): Int = size
10 | override fun createFragment(position: Int): Fragment = ListFragment.newInstance(position, calendar)
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/others/GlideApp.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.others
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import ani.saikou.okHttpClient
6 | import com.bumptech.glide.Glide
7 | import com.bumptech.glide.GlideBuilder
8 | import com.bumptech.glide.Registry
9 | import com.bumptech.glide.annotation.GlideModule
10 | import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
11 | import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory
12 | import com.bumptech.glide.load.model.GlideUrl
13 | import com.bumptech.glide.module.AppGlideModule
14 | import java.io.InputStream
15 |
16 |
17 | @GlideModule
18 | class SaikouGlideApp : AppGlideModule(){
19 | @SuppressLint("CheckResult")
20 | override fun applyOptions(context: Context, builder: GlideBuilder) {
21 | super.applyOptions(context, builder)
22 | val diskCacheSizeBytes = 1024 * 1024 * 100 // 100 MiB
23 | builder.apply {
24 | setDiskCache(InternalCacheDiskCacheFactory(context, "img", diskCacheSizeBytes.toLong()))
25 | }
26 | }
27 |
28 | override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
29 | registry.replace(
30 | GlideUrl::class.java,
31 | InputStream::class.java,
32 | OkHttpUrlLoader.Factory(okHttpClient)
33 | )
34 | super.registerComponents(context, glide, registry)
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/others/Idiosyncrasy.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNCHECKED_CAST", "DEPRECATION")
2 |
3 | package ani.saikou.others
4 |
5 | import android.content.Intent
6 | import android.os.Build
7 | import android.os.Bundle
8 | import java.io.Serializable
9 |
10 | inline fun Bundle.getSerialized(key: String): T? {
11 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
12 | this.getSerializable(key, T::class.java)
13 | else
14 | this.getSerializable(key) as? T
15 | }
16 |
17 | inline fun Intent.getSerialized(key: String): T? {
18 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
19 | this.getSerializableExtra(key, T::class.java)
20 | else
21 | this.getSerializableExtra(key) as? T
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/others/ResettableTimer.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.others
2 |
3 | import java.util.*
4 | import java.util.concurrent.atomic.*
5 |
6 | class ResettableTimer {
7 | var resetLock = AtomicBoolean(false)
8 | var timer = Timer()
9 | fun reset(timerTask: TimerTask, delay: Long) {
10 | if (!resetLock.getAndSet(true)) {
11 | timer.cancel()
12 | timer.purge()
13 | timer = Timer()
14 | timer.schedule(object : TimerTask() {
15 | override fun run() {
16 | if (!resetLock.getAndSet(true)) {
17 | timerTask.run()
18 | timer.cancel()
19 | timer.purge()
20 | resetLock.set(false)
21 | }
22 | }
23 | }, delay)
24 | resetLock.set(false)
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/others/webview/CloudFlare.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.others.webview
2 |
3 | import android.graphics.Bitmap
4 | import android.webkit.WebView
5 | import android.webkit.WebViewClient
6 | import ani.saikou.FileUrl
7 |
8 | class CloudFlare(override val location: FileUrl) : WebViewBottomDialog() {
9 | val cfTag = "cf_clearance"
10 |
11 | override var title = "Cloudflare Bypass"
12 | override val webViewClient = object : WebViewClient() {
13 | override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
14 | val cookie = cookies.getCookie(url.toString())
15 | if (cookie?.contains(cfTag) == true) {
16 | val clearance = cookie.substringAfter("$cfTag=").substringBefore(";")
17 | privateCallback.invoke(mapOf(cfTag to clearance))
18 | }
19 | super.onPageStarted(view, url, favicon)
20 | }
21 | }
22 |
23 | companion object {
24 | fun newInstance(url: FileUrl) = CloudFlare(url)
25 | fun newInstance(url: String) = CloudFlare(FileUrl(url))
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/AnimeExtractors.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime
2 |
3 | import android.net.Uri
4 | import ani.saikou.parsers.anime.extractors.*
5 |
6 | object AnimeExtractors {
7 |
8 | fun getExtractor(name: String, server: VideoServer): VideoExtractor? {
9 | var domain = Uri.parse(server.embed.url).host ?: return null
10 | if (domain.startsWith("www.")) {domain = domain.substring(4)}
11 |
12 | val extractor: VideoExtractor? = when (domain) {
13 | "filemoon.to", "filemoon.sx" -> FileMoon(server)
14 | "rapid-cloud.co" -> RapidCloud(server)
15 | "streamtape.com" -> StreamTape(server)
16 | "vidstream.pro" -> VidStreaming(server)
17 | "mp4upload.com" -> Mp4Upload(server)
18 | "playtaku.net","goone.pro" -> GogoCDN(server)
19 | "alions.pro" -> ALions(server)
20 | "awish.pro" -> AWish(server)
21 | "dood.wf" -> DoodStream(server)
22 | "ok.ru" -> OkRu(server)
23 | else -> {
24 | println("$name : No extractor found for: $domain | ${server.embed.url}")
25 | null
26 | }
27 | }
28 | return extractor
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/AnimeSources.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime
2 |
3 | import ani.saikou.Lazier
4 | import ani.saikou.lazyList
5 | import ani.saikou.parsers.BaseParser
6 | import ani.saikou.parsers.WatchSources
7 | import ani.saikou.parsers.anime.sources.AllAnime
8 | import ani.saikou.parsers.anime.sources.AniWave
9 | import ani.saikou.parsers.anime.sources.AnimeDao
10 | import ani.saikou.parsers.anime.sources.AnimePahe
11 | import ani.saikou.parsers.anime.sources.Animension
12 | import ani.saikou.parsers.anime.sources.Gogo
13 | import ani.saikou.parsers.anime.sources.Haho
14 | import ani.saikou.parsers.anime.sources.HentaiFF
15 | import ani.saikou.parsers.anime.sources.HentaiMama
16 | import ani.saikou.parsers.anime.sources.HentaiStream
17 | import ani.saikou.parsers.anime.sources.Kaido
18 |
19 | object AnimeSources : WatchSources() {
20 | override val list: List> = lazyList(
21 | // "Dummy" to ::AnimeDummy,
22 | "Gogo" to ::Gogo,
23 | "AllAnime" to ::AllAnime,
24 | "AnimeDao" to ::AnimeDao,
25 | "AnimePahe" to ::AnimePahe,
26 | "Animension" to ::Animension,
27 | "Kaido" to ::Kaido,
28 | "AniWave" to ::AniWave,
29 | // "Sflix" to ::SFlix,
30 |
31 |
32 | )
33 | }
34 |
35 | object HAnimeSources : WatchSources() {
36 | private val aList: List> = lazyList(
37 | "Haho" to ::Haho,
38 | "HentaiMama" to ::HentaiMama,
39 | "HentaiStream" to ::HentaiStream,
40 | "HentaiFF" to ::HentaiFF,
41 |
42 | )
43 |
44 | override val list = listOf(aList, AnimeSources.list).flatten()
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/ALions.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.client
4 | import ani.saikou.others.JsUnpacker
5 | import ani.saikou.parsers.anime.Video
6 | import ani.saikou.parsers.anime.VideoContainer
7 | import ani.saikou.parsers.anime.VideoExtractor
8 | import ani.saikou.parsers.anime.VideoServer
9 | import ani.saikou.parsers.anime.VideoType
10 |
11 | class ALions(override val server: VideoServer) : VideoExtractor() {
12 | override suspend fun extract(): VideoContainer {
13 | val player = client.get(server.embed.url).document.html()
14 | val script = Regex("").find(player)!!.groups[1]!!.value // I could do this with nice-http html parser, but that's too much effort and regex only needs 3ms
15 |
16 | val url = Regex("file:\"([^\"]+)\"\\}").find(JsUnpacker(script).unpack()!!)!!.groups[1]!!.value
17 | return VideoContainer(listOf(Video(null, VideoType.M3U8, url)))
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/AWish.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.client
4 | import ani.saikou.parsers.anime.Video
5 | import ani.saikou.parsers.anime.VideoContainer
6 | import ani.saikou.parsers.anime.VideoExtractor
7 | import ani.saikou.parsers.anime.VideoServer
8 | import ani.saikou.parsers.anime.VideoType
9 |
10 | class AWish(override val server: VideoServer) : VideoExtractor() {
11 | override suspend fun extract(): VideoContainer {
12 | val player = client.get(server.embed.url).document.html()
13 |
14 | val url = Regex("file:\"([^\"]+)\"\\}").find(player)!!.groups[1]!!.value
15 | return VideoContainer(listOf(Video(null, VideoType.M3U8, url)))
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/Animeflix.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.client
4 | import ani.saikou.parsers.anime.Video
5 | import ani.saikou.parsers.anime.VideoContainer
6 | import ani.saikou.parsers.anime.VideoExtractor
7 | import ani.saikou.parsers.anime.VideoServer
8 | import ani.saikou.parsers.anime.VideoType
9 | import org.json.JSONObject
10 |
11 | class Animeflix(override val server: VideoServer) : VideoExtractor() {
12 | override suspend fun extract(): VideoContainer {
13 | val response = client.get(server.embed.url,
14 | headers = mapOf("accept-language" to "en-US,en;q=0.9")
15 | )
16 | val responseBody = response.body?.string()
17 | val json = JSONObject(responseBody)
18 | val source = json.getString("source")
19 |
20 | println("vajha vahj as : $source")
21 |
22 | val player = client.get(source, headers = mapOf("accept-language" to "en-US,en;q=0.9")).document.html()
23 | val url = Regex("const source = `([^`]+)`").find(player)!!.groups[1]!!.value
24 | return VideoContainer(listOf(Video(null, VideoType.M3U8, url)))
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/BetaPlayer.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime
2 |
3 | import ani.saikou.FileUrl
4 | import ani.saikou.Mapper
5 | import ani.saikou.client
6 | import ani.saikou.parsers.*
7 | import kotlinx.serialization.SerialName
8 | import kotlinx.serialization.Serializable
9 |
10 | class BetaPlayer(override val server: VideoServer) : VideoExtractor() {
11 | override suspend fun extract(): VideoContainer {
12 | // This needs to be implemented differently
13 | // but I need to find an anime which uses https://kaast1.com/betaplayer/ instead of
14 | // betaplayer.life first
15 | if (server.embed.url.contains("kaast1")) return VideoContainer(listOf())
16 |
17 | val res =
18 | client
19 | .get(server.embed.url, server.embed.headers)
20 | .text
21 | .substringAfter("JSON.parse('")
22 | .substringBefore("')")
23 |
24 | val json = Mapper.parse("{\"files\":$res}")
25 | return VideoContainer(
26 | json.files.map() { video ->
27 | return@map Video(
28 | video.quality.removeSuffix("p").toInt(),
29 | VideoType.CONTAINER,
30 | FileUrl(video.link, server.embed.headers),
31 | )
32 | },
33 | )
34 | }
35 |
36 | @Serializable
37 | data class BetaPlayerJSON(val files: List) {
38 | @Serializable
39 | data class BetaPlayerFiles(
40 | @SerialName("label") val quality: String,
41 | @SerialName("file") val link: String,
42 | val type: String,
43 | )
44 | }
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/DoodStream.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import android.net.Uri
4 | import ani.saikou.FileUrl
5 | import ani.saikou.client
6 | import ani.saikou.findBetween
7 | import ani.saikou.getSize
8 | import ani.saikou.parsers.anime.Video
9 | import ani.saikou.parsers.anime.VideoContainer
10 | import ani.saikou.parsers.anime.VideoExtractor
11 | import ani.saikou.parsers.anime.VideoServer
12 | import ani.saikou.parsers.anime.VideoType
13 | import java.util.*
14 |
15 | class DoodStream(override val server: VideoServer) : VideoExtractor() {
16 | override suspend fun extract(): VideoContainer {
17 | val domain = "https://" + Uri.parse(server.embed.url).host!!
18 | val res = client.get(server.embed.url).text
19 | val hash = res.findBetween("/pass_md5/", "'")!!
20 | val token = res.findBetween("token=", "&")!!
21 | val url = client.get("$domain/pass_md5/$hash", referer = domain).text
22 | val link = FileUrl("$url?token=$token&expiry=${Date().time}}", mapOf("referer" to domain))
23 | println(link)
24 | return VideoContainer(
25 | listOf(Video(null, VideoType.CONTAINER, link, getSize(link)))
26 | )
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/FPlayer.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.asyncMap
4 | import ani.saikou.client
5 | import ani.saikou.getSize
6 | import ani.saikou.parsers.anime.Video
7 | import ani.saikou.parsers.anime.VideoContainer
8 | import ani.saikou.parsers.anime.VideoExtractor
9 | import ani.saikou.parsers.anime.VideoServer
10 | import ani.saikou.parsers.anime.VideoType
11 | import ani.saikou.tryWithSuspend
12 | import kotlinx.serialization.Serializable
13 |
14 | class FPlayer(override val server: VideoServer) : VideoExtractor() {
15 |
16 | override suspend fun extract(): VideoContainer {
17 | val url = server.embed.url
18 | val apiLink = url.replace("/v/", "/api/source/")
19 | return tryWithSuspend {
20 | val json = client.post(apiLink, referer = url).parsed()
21 | if (json.success) {
22 | VideoContainer(json.data?.asyncMap {
23 | Video(
24 | it.label.replace("p", "").toIntOrNull(),
25 | VideoType.CONTAINER,
26 | it.file,
27 | getSize(it.file)
28 | )
29 | }?: listOf())
30 | } else null
31 | } ?: VideoContainer(listOf())
32 | }
33 |
34 | @Serializable
35 | private data class Data(
36 | val file: String,
37 | val label: String
38 | )
39 |
40 | @Serializable
41 | private data class Json(
42 | val success: Boolean,
43 | val data: List?
44 | )
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/FileMoon.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.FileUrl
4 | import ani.saikou.client
5 | import ani.saikou.getSize
6 | import ani.saikou.others.JsUnpacker
7 | import ani.saikou.parsers.anime.Video
8 | import ani.saikou.parsers.anime.VideoContainer
9 | import ani.saikou.parsers.anime.VideoExtractor
10 | import ani.saikou.parsers.anime.VideoServer
11 | import ani.saikou.parsers.anime.VideoType
12 |
13 | private val packedRegex = Regex("""eval\(function\(p,a,c,k,e,.*\)\)""")
14 | private fun getPacked(string: String): String? {
15 | return packedRegex.find(string)?.value
16 | }
17 |
18 | private fun getAndUnpack(string: String): String {
19 | val packedText = getPacked(string)
20 | return JsUnpacker(packedText).unpack() ?: string
21 | }
22 | class FileMoon(override val server: VideoServer) : VideoExtractor() {
23 | override suspend fun extract(): VideoContainer {
24 | val page = client.get(server.embed.url)
25 | val unpacked = getAndUnpack(page.text)
26 | val link = Regex("file:\"(.+?)\"").find(unpacked)?.groupValues?.last()
27 |
28 | link?.let {
29 | return VideoContainer(
30 | listOf(
31 | Video(
32 | null,
33 | VideoType.M3U8,
34 | FileUrl(link, mapOf("Referer" to server.embed.url)),
35 | getSize(link)
36 | )
37 | )
38 | )
39 | }
40 | return VideoContainer(listOf())
41 |
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/Maverickki.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime
2 |
3 | import android.net.Uri
4 | import ani.saikou.Mapper
5 | import ani.saikou.client
6 | import ani.saikou.parsers.*
7 | import kotlinx.serialization.Serializable
8 |
9 | class Maverickki(override val server: VideoServer) : VideoExtractor() {
10 | override suspend fun extract(): VideoContainer {
11 | val host = "https://" + Uri.parse(server.embed.url).host
12 | val res =
13 | client
14 | .get(server.embed.url.replace("/embed/", "/api/source/"), server.embed.headers)
15 | .body
16 | .string()
17 | val json = Mapper.parse(res)
18 |
19 | val videos = listOf(Video(null, VideoType.M3U8, host + json.hls))
20 |
21 | val subtitles =
22 | json.subtitles?.map { sub ->
23 | Subtitle(
24 | sub.name,
25 | host + sub.src,
26 | // SubtitleType.VTT // Let this be auto-filled
27 | )
28 | }
29 | ?: listOf()
30 |
31 | return VideoContainer(videos, subtitles)
32 | }
33 |
34 | @Serializable
35 | data class MaverickkiResponse(val hls: String, val subtitles: List?) {
36 | @Serializable
37 | data class MaverickkiSubtitles(
38 | val name: String,
39 | val src: String,
40 | )
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/Mp4Upload.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.FileUrl
4 | import ani.saikou.client
5 | import ani.saikou.getSize
6 | import ani.saikou.parsers.anime.Video
7 | import ani.saikou.parsers.anime.VideoContainer
8 | import ani.saikou.parsers.anime.VideoExtractor
9 | import ani.saikou.parsers.anime.VideoServer
10 | import ani.saikou.parsers.anime.VideoType
11 |
12 | class Mp4Upload(override val server: VideoServer) : VideoExtractor() {
13 | override suspend fun extract(): VideoContainer {
14 | val link = client.get(server.embed.url).document
15 | .select("script").html()
16 | .substringAfter("src: \"").substringBefore("\"")
17 | val host = link.substringAfter("https://").substringBefore("/")
18 | val file = FileUrl(link, mapOf("host" to host))
19 | return VideoContainer(
20 | listOf(Video(null, VideoType.CONTAINER, file, getSize(file)))
21 | )
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/OkRu.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.client
4 | import ani.saikou.parsers.anime.Video
5 | import ani.saikou.parsers.anime.VideoContainer
6 | import ani.saikou.parsers.anime.VideoExtractor
7 | import ani.saikou.parsers.anime.VideoServer
8 | import ani.saikou.parsers.anime.VideoType
9 |
10 | class OkRu(override val server: VideoServer) : VideoExtractor() {
11 | override suspend fun extract(): VideoContainer {
12 | val player = client.get(server.embed.url).document.html()
13 | val mediaUrl = Regex("https://vd\\d+\\.mycdn\\.me/e[^\\\\]+").find(player)
14 |
15 | return VideoContainer(
16 | listOf(
17 | Video(null, VideoType.M3U8, mediaUrl!!.value),
18 | Video(null, VideoType.DASH, mediaUrl.next()!!.value)
19 | )
20 | )
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/PinkBird.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime
2 |
3 | import android.util.Base64
4 | import ani.saikou.FileUrl
5 | import ani.saikou.Mapper
6 | import ani.saikou.client
7 | import ani.saikou.parsers.*
8 | import kotlinx.serialization.SerialName
9 | import kotlinx.serialization.Serializable
10 |
11 | class PinkBird(override val server: VideoServer) : VideoExtractor() {
12 | override suspend fun extract(): VideoContainer {
13 | val slice = client.get(server.embed.url, server.embed.headers).body.string()
14 | val json = Mapper.parse(slice)
15 |
16 | return VideoContainer(
17 | videos =
18 | json.sources.map { source ->
19 | return@map Video(
20 | null,
21 | VideoType.M3U8,
22 | FileUrl(
23 | "https://pb.kaast1.com/manifest/${Base64.decode(source.encodedBase64, Base64.NO_WRAP).decodeToString()}/master.m3u8",
24 | server.embed.headers
25 | ),
26 | )
27 | }
28 | )
29 | }
30 |
31 | @Serializable
32 | data class PinkDuckJSON(
33 | @SerialName("data") val sources: List,
34 | ) {
35 | @Serializable
36 | data class PinkDuckSource(
37 | @SerialName("eid") val encodedBase64: String,
38 | )
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/StreamTape.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.FileUrl
4 | import ani.saikou.client
5 | import ani.saikou.getSize
6 | import ani.saikou.parsers.anime.Video
7 | import ani.saikou.parsers.anime.VideoContainer
8 | import ani.saikou.parsers.anime.VideoExtractor
9 | import ani.saikou.parsers.anime.VideoServer
10 | import ani.saikou.parsers.anime.VideoType
11 |
12 | class StreamTape(override val server: VideoServer) : VideoExtractor() {
13 | private val linkRegex = Regex("""'robotlink'\)\.innerHTML = '(.+?)'\+ \('(.+?)'\)""")
14 |
15 | override suspend fun extract(): VideoContainer {
16 | val reg = linkRegex.find(client.get(server.embed.url.replace("tape.com","adblocker.xyz")).text)?:return VideoContainer(listOf())
17 | val extractedUrl = FileUrl("https:${reg.groups[1]!!.value + reg.groups[2]!!.value.substring(3)}")
18 | return VideoContainer(listOf(Video(null, VideoType.CONTAINER, extractedUrl, getSize(extractedUrl))))
19 | }
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/extractors/VidStreaming.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.extractors
2 |
3 | import ani.saikou.client
4 | import ani.saikou.findBetween
5 | import ani.saikou.parsers.anime.Video
6 | import ani.saikou.parsers.anime.VideoContainer
7 | import ani.saikou.parsers.anime.VideoExtractor
8 | import ani.saikou.parsers.anime.VideoServer
9 | import ani.saikou.parsers.anime.VideoType
10 |
11 | class VidStreaming(override val server: VideoServer) : VideoExtractor() {
12 | override suspend fun extract(): VideoContainer {
13 | if(server.embed.url.contains("srcd")) {
14 | val link = client.get(server.embed.url).text.findBetween("\"file\": '", "',")!!
15 | return VideoContainer(listOf(Video(null, VideoType.M3U8, link, null)))
16 | }
17 | val url = client.get(server.embed.url).document.select("iframe").attr("src")
18 | if(url.contains("filemoon")) {
19 | return FileMoon(VideoServer("FileMoon", url)).extract()
20 | }
21 | return GogoCDN(VideoServer("GogoCDN", url)).extract()
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/anime/sources/AnimeDummy.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.anime.sources
2 |
3 | import ani.saikou.parsers.ShowResponse
4 | import ani.saikou.parsers.anime.AnimeParser
5 | import ani.saikou.parsers.anime.Episode
6 | import ani.saikou.parsers.anime.VideoServer
7 |
8 | class AnimeDummy : AnimeParser() {
9 |
10 | override val name = "Dummy"
11 | override val saveName = "anime_dummy"
12 | override val hostUrl = "https://example.com"
13 | override val isDubAvailableSeparately = false
14 |
15 | override suspend fun loadEpisodes(
16 | animeLink: String,
17 | extra: Map?
18 | ): List {
19 | TODO("Not yet implemented")
20 | }
21 |
22 | override suspend fun loadVideoServers(
23 | episodeLink: String,
24 | extra: Map?
25 | ): List {
26 | TODO("Not yet implemented")
27 | }
28 |
29 | override suspend fun search(query: String): List {
30 | TODO("Not yet implemented")
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/manga/MangaSources.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.manga
2 |
3 | import ani.saikou.Lazier
4 | import ani.saikou.lazyList
5 | import ani.saikou.parsers.BaseParser
6 | import ani.saikou.parsers.MangaReadSources
7 | import ani.saikou.parsers.manga.sources.AllAnime
8 | import ani.saikou.parsers.manga.sources.AsuraScans
9 | import ani.saikou.parsers.manga.sources.Manga4Life
10 | import ani.saikou.parsers.manga.sources.MangaBuddy
11 | import ani.saikou.parsers.manga.sources.MangaDex
12 | import ani.saikou.parsers.manga.sources.MangaKakalot
13 | import ani.saikou.parsers.manga.sources.MangaKatana
14 | import ani.saikou.parsers.manga.sources.MangaPill
15 | import ani.saikou.parsers.manga.sources.MangaRead
16 | import ani.saikou.parsers.manga.sources.Manhwa18
17 | import ani.saikou.parsers.manga.sources.MmScans
18 | import ani.saikou.parsers.manga.sources.NineHentai
19 | import ani.saikou.parsers.manga.sources.Toonily
20 |
21 | object MangaSources : MangaReadSources() {
22 | override val list: List> = lazyList(
23 | "AsuraScans" to ::AsuraScans,
24 | "MangaKakalot" to ::MangaKakalot,
25 | "MangaBuddy" to ::MangaBuddy,
26 | "MangaPill" to ::MangaPill,
27 | "MangaDex" to ::MangaDex,
28 | "AllAnime" to ::AllAnime,
29 | "Toonily" to ::Toonily,
30 | "MmScans" to ::MmScans,
31 | "MangaKatana" to ::MangaKatana,
32 | "Manga4Life" to ::Manga4Life,
33 | "MangaRead" to ::MangaRead
34 |
35 | )
36 | }
37 |
38 | object HMangaSources : MangaReadSources() {
39 | private val aList: List> = lazyList(
40 | "NineHentai" to ::NineHentai,
41 | "Manhwa18" to ::Manhwa18,
42 | )
43 | override val list = listOf(aList, MangaSources.list).flatten()
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/manga/sources/MangaDummy.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.manga.sources
2 |
3 | import ani.saikou.parsers.ShowResponse
4 | import ani.saikou.parsers.manga.MangaChapter
5 | import ani.saikou.parsers.manga.MangaImage
6 | import ani.saikou.parsers.manga.MangaParser
7 |
8 | class MangaDummy : MangaParser() {
9 |
10 | override val name = "Dummy"
11 | override val saveName = "manga_dummy"
12 | override val hostUrl = "https://example.com"
13 |
14 | override suspend fun loadChapters(
15 | mangaLink: String,
16 | extra: Map?
17 | ): List {
18 | TODO("Not yet implemented")
19 | }
20 |
21 | override suspend fun loadImages(chapterLink: String): List {
22 | TODO("Not yet implemented")
23 | }
24 |
25 | override suspend fun search(query: String): List {
26 | TODO("Not yet implemented")
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/manga/sources/MangaPill.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.manga.sources
2 |
3 | import ani.saikou.FileUrl
4 | import ani.saikou.client
5 | import ani.saikou.parsers.manga.MangaChapter
6 | import ani.saikou.parsers.manga.MangaImage
7 | import ani.saikou.parsers.manga.MangaParser
8 | import ani.saikou.parsers.ShowResponse
9 |
10 | class MangaPill : MangaParser() {
11 |
12 | override val name = "MangaPill"
13 | override val saveName = "manga_pill"
14 | override val hostUrl = "https://mangapill.com"
15 |
16 | val headers = mapOf("referer" to hostUrl)
17 |
18 | override suspend fun loadChapters(
19 | mangaLink: String, extra: Map?
20 | ): List {
21 | return client.get(mangaLink).document.select("#chapters > div > a").map {
22 | val chap = it.text().replace("Chapter ", "")
23 | MangaChapter(chap, hostUrl + it.attr("href"))
24 | }
25 | }
26 |
27 | override suspend fun loadImages(chapterLink: String): List {
28 | return client.get(chapterLink).document.select("img.js-page").map {
29 | MangaImage(FileUrl(it.attr("data-src"), headers))
30 | }
31 |
32 | }
33 |
34 | override suspend fun search(query: String): List {
35 | val link = "$hostUrl/quick-search?q=${encode(query)}"
36 | return client.get(link).document.select(".bg-card").map {
37 | ShowResponse(
38 | it.select(".font-black").text(),
39 | hostUrl + it.attr("href"),
40 | FileUrl(it.select("img").attr("src"), headers)
41 | )
42 | }
43 |
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/novel/NovelSources.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.novel
2 |
3 | import ani.saikou.Lazier
4 | import ani.saikou.lazyList
5 | import ani.saikou.parsers.BaseParser
6 | import ani.saikou.parsers.NovelReadSources
7 | import ani.saikou.parsers.novel.sources.NovelDummy
8 |
9 | object NovelSources : NovelReadSources() {
10 | override val list: List> = lazyList(
11 | "Dummy" to ::NovelDummy,
12 | )
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/parsers/novel/sources/NovelDummy.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.parsers.novel.sources
2 |
3 | import ani.saikou.parsers.ShowResponse
4 | import ani.saikou.parsers.novel.Book
5 | import ani.saikou.parsers.novel.NovelParser
6 |
7 | class NovelDummy : NovelParser(){
8 |
9 | override val name = "Dummy"
10 | override val saveName = "novel_dummy"
11 | override val hostUrl = "https://example.com"
12 | override val volumeRegex: Regex = Regex("")
13 |
14 | override suspend fun loadBook(link: String, extra: Map?): Book {
15 | TODO("Not yet implemented")
16 | }
17 |
18 | override suspend fun search(query: String): List {
19 | TODO("Not yet implemented")
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/settings/CurrentNovelReaderSettings.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.settings
2 |
3 | import java.io.Serializable
4 |
5 | data class CurrentNovelReaderSettings(
6 | var currentThemeName: String = "Default",
7 | var layout: Layouts = Layouts.PAGED,
8 | var dualPageMode: CurrentReaderSettings.DualPageModes = CurrentReaderSettings.DualPageModes.Automatic,
9 | var lineHeight: Float = 1.4f,
10 | var margin: Float = 0.06f,
11 | var justify: Boolean = true,
12 | var hyphenation: Boolean = true,
13 | var useDarkTheme: Boolean = false,
14 | var invert: Boolean = false,
15 | var maxInlineSize: Int = 720,
16 | var maxBlockSize: Int = 1440,
17 | var horizontalScrollBar: Boolean = true,
18 | var keepScreenOn: Boolean = false,
19 | var volumeButtons: Boolean = false,
20 | ) : Serializable {
21 |
22 | enum class Layouts(val string: String) {
23 | PAGED("Paged"),
24 | SCROLLED("Scrolled");
25 |
26 | companion object {
27 | operator fun get(value: Int) = values().firstOrNull { it.ordinal == value }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/settings/Developer.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.settings
2 |
3 | data class Developer(
4 | val name: String,
5 | val pfp: String,
6 | val role: String,
7 | val url: String
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/settings/DevelopersAdapter.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.settings
2 |
3 | import android.view.LayoutInflater
4 | import android.view.ViewGroup
5 | import androidx.recyclerview.widget.RecyclerView
6 | import ani.saikou.databinding.ItemDeveloperBinding
7 | import ani.saikou.loadData
8 | import ani.saikou.loadImage
9 | import ani.saikou.openLinkInBrowser
10 | import ani.saikou.setAnimation
11 |
12 | class DevelopersAdapter(private val developers: Array) :
13 | RecyclerView.Adapter() {
14 | private val uiSettings = loadData("ui_settings") ?: UserInterfaceSettings()
15 |
16 | inner class DeveloperViewHolder(val binding: ItemDeveloperBinding) : RecyclerView.ViewHolder(binding.root) {
17 | init {
18 | itemView.setOnClickListener {
19 | openLinkInBrowser(developers[bindingAdapterPosition].url)
20 | }
21 | }
22 | }
23 |
24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DeveloperViewHolder {
25 | return DeveloperViewHolder(ItemDeveloperBinding.inflate(LayoutInflater.from(parent.context), parent, false))
26 | }
27 |
28 | override fun onBindViewHolder(holder: DeveloperViewHolder, position: Int) {
29 | val b = holder.binding
30 | setAnimation(b.root.context, b.root, uiSettings)
31 | val dev = developers[position]
32 | b.devName.text = dev.name
33 | b.devProfile.loadImage(dev.pfp)
34 | b.devRole.text = dev.role
35 | }
36 |
37 | override fun getItemCount(): Int = developers.size
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/settings/NovelReaderSettings.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.settings
2 |
3 | import java.io.Serializable
4 |
5 | data class NovelReaderSettings(
6 | var showSource: Boolean = true,
7 | var showSystemBars: Boolean = false,
8 | var default: CurrentNovelReaderSettings = CurrentNovelReaderSettings(),
9 | var askIndividual: Boolean = true,
10 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/settings/PlayerSettings.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.settings
2 |
3 | import java.io.Serializable
4 |
5 | data class PlayerSettings(
6 | //Video
7 | var videoInfo: Boolean = true,
8 | var defaultSpeed: Int = 5,
9 | var cursedSpeeds: Boolean = false,
10 | var resize: Int = 0,
11 |
12 | //Subtitles
13 | var subtitles: Boolean = true,
14 | var primaryColor: Int = 4,
15 | var secondaryColor: Int = 0,
16 | var outline: Int = 0,
17 | var subBackground: Int = 0,
18 | var subWindow: Int = 0,
19 | var font: Int = 0,
20 | var fontSize: Int = 20,
21 | var locale: Int = 2,
22 |
23 | //TimeStamps
24 | var timeStampsEnabled: Boolean = true,
25 | var useProxyForTimeStamps: Boolean = true,
26 | var showTimeStampButton: Boolean = true,
27 |
28 | //Auto
29 | var autoSkipOPED: Boolean = false,
30 | var autoPlay: Boolean = true,
31 | var autoSkipFiller: Boolean = false,
32 |
33 | //Update Progress
34 | var askIndividual: Boolean = true,
35 | var updateForH: Boolean = false,
36 | var watchPercentage: Float = 0.8f,
37 |
38 | //Behaviour
39 | var alwaysContinue: Boolean = true,
40 | var focusPause: Boolean = true,
41 | var gestures: Boolean = true,
42 | var doubleTap: Boolean = true,
43 | var seekTime: Int = 10,
44 | var skipTime: Int = 85,
45 |
46 | //Other
47 | var cast: Boolean = false,
48 | var pip: Boolean = true
49 | ) : Serializable
50 |
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/settings/ReaderSettings.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.settings
2 |
3 | import java.io.Serializable
4 |
5 | data class ReaderSettings(
6 | var showSource: Boolean = true,
7 | var showSystemBars: Boolean = false,
8 |
9 | var autoDetectWebtoon: Boolean = true,
10 | var default: CurrentReaderSettings = CurrentReaderSettings(),
11 |
12 | var askIndividual: Boolean = true,
13 | var updateForH: Boolean = false
14 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/settings/UserInterfaceSettings.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.settings
2 |
3 | import java.io.Serializable
4 |
5 | data class UserInterfaceSettings(
6 | var darkMode: Boolean? = null,
7 | var showYtButton: Boolean = true,
8 | var animeDefaultView: Int = 0,
9 | var mangaDefaultView: Int = 0,
10 |
11 | //App
12 | var immersiveMode: Boolean = false,
13 | var smallView: Boolean = true,
14 | var defaultStartUpTab: Int = 1,
15 | var homeLayoutShow: MutableList = mutableListOf(true, false, false, true, false, false, true),
16 |
17 | //Animations
18 | var bannerAnimations: Boolean = true,
19 | var layoutAnimations: Boolean = true,
20 | var animationSpeed: Float = 1f
21 |
22 | ) : Serializable
--------------------------------------------------------------------------------
/app/src/main/java/ani/saikou/subcriptions/SubscriptionWorker.kt:
--------------------------------------------------------------------------------
1 | package ani.saikou.subcriptions
2 |
3 | import android.content.Context
4 | import androidx.work.*
5 | import ani.saikou.loadData
6 | import ani.saikou.subcriptions.Subscription.Companion.defaultTime
7 | import ani.saikou.subcriptions.Subscription.Companion.timeMinutes
8 | import kotlinx.coroutines.Dispatchers
9 | import kotlinx.coroutines.withContext
10 | import java.util.concurrent.*
11 |
12 | class SubscriptionWorker(val context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
13 |
14 | override suspend fun doWork(): Result {
15 | withContext(Dispatchers.IO){
16 | Subscription.perform(context)
17 | }
18 | return Result.success()
19 | }
20 |
21 | companion object {
22 |
23 | private const val SUBSCRIPTION_WORK_NAME = "work_subscription"
24 | fun enqueue(context: Context) {
25 | val curTime = loadData("subscriptions_time") ?: defaultTime
26 | if(timeMinutes[curTime]>0L) {
27 | val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
28 | val periodicSyncDataWork = PeriodicWorkRequest.Builder(
29 | SubscriptionWorker::class.java, 6, TimeUnit.HOURS
30 | ).apply {
31 | addTag(SUBSCRIPTION_WORK_NAME)
32 | setConstraints(constraints)
33 | }.build()
34 | WorkManager.getInstance(context).enqueueUniquePeriodicWork(
35 | SUBSCRIPTION_WORK_NAME, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, periodicSyncDataWork
36 | )
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/res/anim/over_shoot.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/color/button_switch_track.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/color/tab_layout_icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/color/tab_layout_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_invert_colors_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bottom_nav.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/buymecofee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/drawable/buymecofee.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/control_background_40dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add.xml:
--------------------------------------------------------------------------------
1 |
7 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_anilist.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_screen_lock_portrait_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_github.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
6 |
8 |
11 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
8 |
11 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_minus.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_myanimelist.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_page_numbering.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_accessible_forward_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_add_circle_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_add_circle_outline_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_alpha_t_box_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_amp_stories_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_animation_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_arrow_back_ios_new_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_arrow_drop_down_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_art_track_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_audiotrack_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_auto_awesome_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_brightness_4_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_brightness_auto_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_brightness_high_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_brightness_medium_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_calendar_today_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_cast_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_close_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_collections_bookmark_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_color_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_date_range_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_dns_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_download_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_edit_note_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_fast_forward_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_fast_rewind_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_favorite_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_favorite_border_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_filter_alt_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_font_size_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_format_text_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_fullscreen_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_grid_view_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_heart_broken_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_help_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_high_quality_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_home_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_image_search_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_import_contacts_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_info_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_lock_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_lock_open_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_movie_filter_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_new_releases_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_notifications_active_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_notifications_none_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_pause_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_person_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_photo_size_select_actual_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_picture_in_picture_alt_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_play_arrow_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_play_circle_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_play_disabled_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_playlist_add_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_playlist_play_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_reader_settings.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_refresh_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_remove_red_eye_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_restaurant_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_screen_rotation_alt_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_sd_card_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_search_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_settings_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_share_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_skip_next_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_skip_previous_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_slow_motion_video_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_smart_button_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_sort_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_source_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_space_bar_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_star_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_straighten_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_subtitles_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_swipe_down_alt_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_swipe_up_alt_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_swipe_vertical_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_sync_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_touch_app_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_translate_variant_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_video_library_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_video_settings_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_view_array_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_view_column_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_view_comfy_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_view_list_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_volume_up_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_skip.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_telegram.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/item_ongoing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/item_score.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/item_type.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/item_user_score.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/kofi_s_tag_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/drawable/kofi_s_tag_dark.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/linear_gradient_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/linear_gradient_black.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/linear_gradient_black_horizontal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/linear_gradient_nav.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/monochrome.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_corner.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rounded_top_nav.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_corner_16dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/spinner_icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/spinner_icon_manga.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ui_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 | -
25 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/font/poppins.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/font/poppins.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/poppins_bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/font/poppins_bold.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/poppins_family.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/font/poppins_semi_bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/font/poppins_semi_bold.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/poppins_thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/font/poppins_thin.ttf
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_exoplayer.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_faq.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
24 |
25 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_genre.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
35 |
36 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_developers.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
27 |
28 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_subtitles.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
21 |
22 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_webview.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
21 |
22 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_anime_watch.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
31 |
32 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_character_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
27 |
28 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_chip.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_count_down.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
22 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_dropdown.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_episodes_recyclerview.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_genre.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
23 |
24 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
16 |
17 |
27 |
28 |
35 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_progressbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_question.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_recyclerview.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_stream.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
23 |
24 |
28 |
29 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_subtitle_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_title_chipgroup.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
27 |
28 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_title_recycler.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_title_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/anime_menu_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/bottom_navbar_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/list_sort_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/manga_menu_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_media.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 | #A8EEEEEE
5 | @color/bg_white
6 | #1C1C1C
7 | #001C1C1C
8 | #40ffffff
9 | #40ffffff
10 | #54000000
11 | #80000000
12 | #29FF6B08
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attr.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF5DAE
4 | #FF007F
5 | #40FF007F
6 | #C50053
7 | #91A6FF
8 | #3358FF
9 | #8091A6FF
10 | #000000
11 | #EEEEEE
12 | @color/bg_white
13 | @color/bg_black
14 | #A8000000
15 | #fff
16 | #00FFFFFF
17 | #40000000
18 | #19000000
19 | #54EEEEEE
20 | #A9FFFFFF
21 | #80FFFFFF
22 | #E63956
23 | #54FF8400
24 |
--------------------------------------------------------------------------------
/app/src/main/res/values/preloaded_fonts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - @font/poppins_bold
5 | - @font/poppins_thin
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
12 |
15 |
18 |
--------------------------------------------------------------------------------
/beta.md:
--------------------------------------------------------------------------------
1 | # 1.2.4
2 |
3 | Hey there, the beta app has now switched to getting immediate updates. (gets updated when the code gets updated)
4 | This means beta can now also have ground breaking bugs with it. (Previously, I avoided this so beta were stable enough to use)
5 |
6 | If you wish still wish to stay on the Beta Version, [click here](https://github.com/saikou-app/saikou/releases)
7 |
8 | If not
9 |
10 | ## You will now be downloading the stable version of the app.
11 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | maven { url 'https://jitpack.io' }
6 | }
7 | ext.kotlin_version = '1.9.10'
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:8.0.2'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20-Beta2"
11 | classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
12 | }
13 | }
14 |
15 | task clean(type: Delete) {
16 | delete rootProject.buildDir
17 | }
18 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | android.defaults.buildfeatures.buildconfig=true
19 | android.nonTransitiveRClass=true
20 | android.nonFinalResIds=true
21 | org.gradle.unsafe.configuration-cache=true
22 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tas33n/saikou/7df974ab4556a0ac1b2a4b90399582b5b711249e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Aug 30 19:57:04 IST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | maven("https://jitpack.io")
6 | }
7 | }
8 |
9 | rootProject.name = "Saikou"
10 | include(":app")
11 |
--------------------------------------------------------------------------------
/stable.md:
--------------------------------------------------------------------------------
1 | # 1.2.7
2 |
3 | - Fixed Gogoanime
4 | - Fixed Animedao
5 | - Removed dead sources
6 |
7 | Please switch to Dontatsu, an improved version with new features and extensions: [Dontotsu](https://github.com/rebelonion/Dantotsu).
8 | Thank you for your understanding and support.
9 |
--------------------------------------------------------------------------------