├── .github └── ISSUE_TEMPLATE │ └── bug-report-.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro ├── schemas │ └── com.arturo254.opentune.db.InternalDatabase │ │ ├── 1.json │ │ ├── 10.json │ │ ├── 11.json │ │ ├── 12.json │ │ ├── 13.json │ │ ├── 14.json │ │ ├── 15.json │ │ ├── 16.json │ │ ├── 17.json │ │ ├── 18.json │ │ ├── 19.json │ │ ├── 2.json │ │ ├── 3.json │ │ ├── 4.json │ │ ├── 5.json │ │ ├── 6.json │ │ ├── 7.json │ │ ├── 8.json │ │ └── 9.json └── src │ ├── debug │ └── res │ │ ├── values │ │ └── app_name.xml │ │ └── xml-v25 │ │ └── shortcuts.xml │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── arturo254 │ │ └── opentune │ │ ├── App.kt │ │ ├── MainActivity.kt │ │ ├── constants │ │ ├── Dimensions.kt │ │ ├── HistorySource.kt │ │ ├── LibraryFilter.kt │ │ ├── MediaSessionConstants.kt │ │ ├── PreferenceKeys.kt │ │ └── StatPeriod.kt │ │ ├── db │ │ ├── Converters.kt │ │ ├── DatabaseDao.kt │ │ ├── MusicDatabase.kt │ │ └── entities │ │ │ ├── Album.kt │ │ │ ├── AlbumArtistMap.kt │ │ │ ├── AlbumEntity.kt │ │ │ ├── AlbumWithSongs.kt │ │ │ ├── Artist.kt │ │ │ ├── ArtistEntity.kt │ │ │ ├── Event.kt │ │ │ ├── EventWithSong.kt │ │ │ ├── FormatEntity.kt │ │ │ ├── LocalItem.kt │ │ │ ├── LyricsEntity.kt │ │ │ ├── PlayCountEntity.kt │ │ │ ├── Playlist.kt │ │ │ ├── PlaylistEntity.kt │ │ │ ├── PlaylistSong.kt │ │ │ ├── PlaylistSongMap.kt │ │ │ ├── PlaylistSongMapPreview.kt │ │ │ ├── RelatedSongMap.kt │ │ │ ├── SearchHistory.kt │ │ │ ├── SetVideoIdEntity.kt │ │ │ ├── Song.kt │ │ │ ├── SongAlbumMap.kt │ │ │ ├── SongArtistMap.kt │ │ │ ├── SongEntity.kt │ │ │ ├── SongWithStats.kt │ │ │ ├── SortedSongAlbumMap.kt │ │ │ └── SortedSongArtistMap.kt │ │ ├── di │ │ └── AppModule.kt │ │ ├── extensions │ │ ├── ContextExt.kt │ │ ├── CoroutineExt.kt │ │ ├── FileExt.kt │ │ ├── ListExt.kt │ │ ├── MediaItemExt.kt │ │ ├── PlayerExt.kt │ │ ├── StringExt.kt │ │ └── UtilExt.kt │ │ ├── lyrics │ │ ├── KuGouLyricsProvider.kt │ │ ├── LrcLibLyricsProvider.kt │ │ ├── LyricsEntry.kt │ │ ├── LyricsHelper.kt │ │ ├── LyricsProvider.kt │ │ ├── LyricsUtils.kt │ │ ├── YouTubeLyricsProvider.kt │ │ └── YouTubeSubtitleLyricsProvider.kt │ │ ├── models │ │ ├── ItemsPage.kt │ │ ├── MediaMetadata.kt │ │ ├── PersistQueue.kt │ │ └── SimilarRecommendation.kt │ │ ├── playback │ │ ├── DownloadUtil.kt │ │ ├── ExoDownloadService.kt │ │ ├── MediaLibrarySessionCallback.kt │ │ ├── MusicService.kt │ │ ├── PlayerConnection.kt │ │ ├── SleepTimer.kt │ │ └── queues │ │ │ ├── EmptyQueue.kt │ │ │ ├── ListQueue.kt │ │ │ ├── LocalAlbumRadio.kt │ │ │ ├── Queue.kt │ │ │ ├── YouTubeAlbumRadio.kt │ │ │ └── YouTubeQueue.kt │ │ ├── ui │ │ ├── component │ │ │ ├── AutoResizeText.kt │ │ │ ├── BigSeekBar.kt │ │ │ ├── BottomSheet.kt │ │ │ ├── BottomSheetMenu.kt │ │ │ ├── BottomSheetPage.kt │ │ │ ├── ChangelogButton.kt │ │ │ ├── ChipsRow.kt │ │ │ ├── CreatePlaylistDialog.kt │ │ │ ├── Dialog.kt │ │ │ ├── EmptyPlaceholder.kt │ │ │ ├── EnhancedPreferenceEntry.kt │ │ │ ├── GridMenu.kt │ │ │ ├── HideOnScrollFAB.kt │ │ │ ├── IconButton.kt │ │ │ ├── Items.kt │ │ │ ├── Library.kt │ │ │ ├── LocaleManager.kt │ │ │ ├── Lyrics.kt │ │ │ ├── NavigationTile.kt │ │ │ ├── NavigationTitle.kt │ │ │ ├── PlayerSlider.kt │ │ │ ├── PlayingIndicator.kt │ │ │ ├── Preference.kt │ │ │ ├── ReleaseNotesCard.kt │ │ │ ├── SearchBar.kt │ │ │ ├── SortHeader.kt │ │ │ └── shimmer │ │ │ │ ├── ButtonPlaceholder.kt │ │ │ │ ├── GridItemPlaceholder.kt │ │ │ │ ├── ListItemPlaceholder.kt │ │ │ │ ├── ShimmerHost.kt │ │ │ │ └── TextPlaceholder.kt │ │ ├── menu │ │ │ ├── AddToPlaylistDialog.kt │ │ │ ├── AlbumMenu.kt │ │ │ ├── ArtistMenu.kt │ │ │ ├── ImportPlaylistDialog.kt │ │ │ ├── LyricsMenu.kt │ │ │ ├── PlayerMenu.kt │ │ │ ├── PlaylistMenu.kt │ │ │ ├── SelectionSongsMenu.kt │ │ │ ├── SongMenu.kt │ │ │ ├── YouTubeAlbumMenu.kt │ │ │ ├── YouTubeArtistMenu.kt │ │ │ ├── YouTubePlaylistMenu.kt │ │ │ └── YouTubeSongMenu.kt │ │ ├── player │ │ │ ├── MiniPlayer.kt │ │ │ ├── PlaybackError.kt │ │ │ ├── Player.kt │ │ │ ├── Queue.kt │ │ │ └── Thumbnail.kt │ │ ├── screens │ │ │ ├── AccountScreen.kt │ │ │ ├── AlbumScreen.kt │ │ │ ├── ExploreScreen.kt │ │ │ ├── HistoryScreen.kt │ │ │ ├── HomeScreen.kt │ │ │ ├── LoginScreen.kt │ │ │ ├── MoodAndGenresScreen.kt │ │ │ ├── NavigationBuilder.kt │ │ │ ├── NewReleaseScreen.kt │ │ │ ├── Screens.kt │ │ │ ├── StatsScreen.kt │ │ │ ├── YouTubeBrowseScreen.kt │ │ │ ├── artist │ │ │ │ ├── ArtistItemsScreen.kt │ │ │ │ ├── ArtistScreen.kt │ │ │ │ └── ArtistSongsScreen.kt │ │ │ ├── library │ │ │ │ ├── CachePlaylistScreen.kt │ │ │ │ ├── LibraryAlbumsScreen.kt │ │ │ │ ├── LibraryArtistsScreen.kt │ │ │ │ ├── LibraryMixScreen.kt │ │ │ │ ├── LibraryPlaylistsScreen.kt │ │ │ │ ├── LibraryScreen.kt │ │ │ │ └── LibrarySongsScreen.kt │ │ │ ├── playlist │ │ │ │ ├── AutoPlaylistScreen.kt │ │ │ │ ├── LocalPlaylistScreen.kt │ │ │ │ ├── OnlinePlaylistScreen.kt │ │ │ │ └── TopPlaylistScreen.kt │ │ │ ├── search │ │ │ │ ├── LocalSearchScreen.kt │ │ │ │ ├── OnlineSearchResult.kt │ │ │ │ └── OnlineSearchScreen.kt │ │ │ └── settings │ │ │ │ ├── AboutScreen.kt │ │ │ │ ├── AccountSettings.kt │ │ │ │ ├── AppearanceSettings.kt │ │ │ │ ├── BackupAndRestore.kt │ │ │ │ ├── ContentSettings.kt │ │ │ │ ├── DiscordLoginScreen.kt │ │ │ │ ├── DiscordSettings.kt │ │ │ │ ├── PlayerSettings.kt │ │ │ │ ├── PrivacySettings.kt │ │ │ │ ├── ProblemSolver.kt │ │ │ │ ├── SettingsScreen.kt │ │ │ │ └── StorageSettings.kt │ │ ├── theme │ │ │ └── Theme.kt │ │ └── utils │ │ │ ├── AppBar.kt │ │ │ ├── FadingEdge.kt │ │ │ ├── ItemWrapper.kt │ │ │ ├── LazyGridSnapLayoutInfoProvider.kt │ │ │ ├── NavControllerUtils.kt │ │ │ ├── ScrollUtils.kt │ │ │ ├── ShapeUtils.kt │ │ │ ├── StringUtils.kt │ │ │ └── YouTubeUtils.kt │ │ ├── utils │ │ ├── CoilBitmapLoader.kt │ │ ├── ComposeDebugUtils.kt │ │ ├── DataStore.kt │ │ ├── DiscordRPC.kt │ │ ├── NetworkUtils.kt │ │ ├── PlaylistImageUtils.kt │ │ ├── StringUtils.kt │ │ ├── SyncUtils.kt │ │ ├── Updater.kt │ │ ├── Utils.kt │ │ ├── YTPlayerUtils.kt │ │ └── potoken │ │ │ ├── JavaScriptUtil.kt │ │ │ ├── PoTokenException.kt │ │ │ ├── PoTokenGenerator.kt │ │ │ ├── PoTokenResult.kt │ │ │ └── PoTokenWebView.kt │ │ └── viewmodels │ │ ├── AccountViewModel.kt │ │ ├── AlbumViewModel.kt │ │ ├── ArtistItemsViewModel.kt │ │ ├── ArtistViewModel.kt │ │ ├── AutoPlaylistViewModel.kt │ │ ├── BackupRestoreViewModel.kt │ │ ├── ExploreViewModel.kt │ │ ├── HistoryViewModel.kt │ │ ├── HomeViewModel.kt │ │ ├── LibraryViewModels.kt │ │ ├── LocalPlaylistViewModel.kt │ │ ├── LocalSearchViewModel.kt │ │ ├── LyricsMenuViewModel.kt │ │ ├── MoodAndGenresViewModel.kt │ │ ├── NewReleaseViewModel.kt │ │ ├── OnlinePlaylistViewModel.kt │ │ ├── OnlineSearchSuggestionViewModel.kt │ │ ├── OnlineSearchViewModel.kt │ │ ├── StatsViewModel.kt │ │ ├── TopPlaylistViewModel.kt │ │ └── YouTubeBrowseViewModel.kt │ ├── logoxd-playstore.png │ └── res │ ├── drawable │ ├── account.xml │ ├── add.xml │ ├── album.xml │ ├── apps.xml │ ├── arrow_back.xml │ ├── arrow_downward.xml │ ├── arrow_forward.xml │ ├── arrow_top_left.xml │ ├── arrow_upward.xml │ ├── artist.xml │ ├── attach_money.xml │ ├── backup.xml │ ├── bedtime.xml │ ├── block.xml │ ├── bookmark.xml │ ├── bookmark_filled.xml │ ├── bug_report.xml │ ├── cached.xml │ ├── car.xml │ ├── casino.xml │ ├── check.xml │ ├── check_box.xml │ ├── check_circle.xml │ ├── chevron_right.xml │ ├── clear_all.xml │ ├── close.xml │ ├── codigo.xml │ ├── compare_arrows.xml │ ├── content_copy.xml │ ├── contrast.xml │ ├── dark_mode.xml │ ├── delete.xml │ ├── delete_history.xml │ ├── deployed_code_update.xml │ ├── deselect.xml │ ├── desktop_windows.xml │ ├── discord.xml │ ├── discover_tune.xml │ ├── donate.xml │ ├── done.xml │ ├── double_arrow.xml │ ├── download.xml │ ├── drag_handle.xml │ ├── edit.xml │ ├── email.xml │ ├── equalizer.xml │ ├── error.xml │ ├── expand_less.xml │ ├── expand_more.xml │ ├── explicit.xml │ ├── explore.xml │ ├── explore_filled.xml │ ├── explore_outlined.xml │ ├── extension.xml │ ├── fast_forward.xml │ ├── favorite.xml │ ├── favorite_border.xml │ ├── feedback.xml │ ├── format_align_center.xml │ ├── format_align_left.xml │ ├── format_color.xml │ ├── funbeta.xml │ ├── github.xml │ ├── google.xml │ ├── gradient.xml │ ├── graphic_eq.xml │ ├── grid_view.xml │ ├── group.xml │ ├── help.xml │ ├── history.xml │ ├── home.xml │ ├── home_filled.xml │ ├── home_outlined.xml │ ├── ia_icon.xml │ ├── image.xml │ ├── info.xml │ ├── input.xml │ ├── language.xml │ ├── liberapay.xml │ ├── library_add.xml │ ├── library_add_check.xml │ ├── library_music.xml │ ├── library_music_filled.xml │ ├── library_music_outlined.xml │ ├── license.xml │ ├── lightbulb.xml │ ├── line_curve.xml │ ├── link.xml │ ├── list.xml │ ├── location_on.xml │ ├── lock.xml │ ├── lock_open.xml │ ├── login.xml │ ├── logout.xml │ ├── lyrics.xml │ ├── manage_search.xml │ ├── menu.xml │ ├── menu_book.xml │ ├── mood.xml │ ├── more_horiz.xml │ ├── more_vert.xml │ ├── music_note.xml │ ├── nav_bar.xml │ ├── navigate_next.xml │ ├── notification_off.xml │ ├── notification_on.xml │ ├── notifications_off.xml │ ├── offline.xml │ ├── opentune.xml │ ├── opentune_monochrome.xml │ ├── palette.xml │ ├── pause.xml │ ├── paypal.xml │ ├── person.xml │ ├── play.xml │ ├── playlist_add.xml │ ├── playlist_import.xml │ ├── playlist_play.xml │ ├── poeditor.xml │ ├── previewalbum.jpg │ ├── queue_music.xml │ ├── radar.webp │ ├── radio.xml │ ├── radio_button_checked.xml │ ├── radio_button_unchecked.xml │ ├── remove.xml │ ├── repeat.xml │ ├── repeat_on.xml │ ├── repeat_one.xml │ ├── repeat_one_on.xml │ ├── replay.xml │ ├── resource_public.xml │ ├── restore.xml │ ├── robot.xml │ ├── schedule.xml │ ├── screenshot.xml │ ├── search.xml │ ├── search_off.xml │ ├── security.xml │ ├── select.xml │ ├── select_all.xml │ ├── settings.xml │ ├── settingsv2.xml │ ├── share.xml │ ├── shortcut_albums.xml │ ├── shortcut_explore.xml │ ├── shortcut_library.xml │ ├── shortcut_playlists.xml │ ├── shortcut_search.xml │ ├── shortcut_songs.xml │ ├── shuffle.xml │ ├── shuffle_on.xml │ ├── signal_cellular_nodata.xml │ ├── similar.xml │ ├── skip_next.xml │ ├── skip_previous.xml │ ├── sliders.xml │ ├── slow_motion_video.xml │ ├── speed.xml │ ├── storage.xml │ ├── support_agent.xml │ ├── swipe.xml │ ├── sync.xml │ ├── tab.xml │ ├── telegram.xml │ ├── tensorflow.xml │ ├── thumb_up.xml │ ├── token.xml │ ├── translate.xml │ ├── trending_up.xml │ ├── tune.xml │ ├── uncheck_box.xml │ ├── update.xml │ ├── verified_user.xml │ ├── volume_off.xml │ ├── volume_up.xml │ ├── waves.xml │ └── wifi_proxy.xml │ ├── mipmap-anydpi-v26 │ └── ic_launcher.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ ├── ic_launcher_background.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_monochrome.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ ├── ic_launcher_background.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_monochrome.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ ├── ic_launcher_background.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_monochrome.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ ├── ic_launcher_background.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_monochrome.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ ├── ic_launcher_background.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_monochrome.png │ ├── values-DE │ └── strings.xml │ ├── values-af-rZA │ └── strings.xml │ ├── values-ar │ └── strings.xml │ ├── values-be │ └── strings.xml │ ├── values-bn-rIN │ └── strings.xml │ ├── values-ca-rES │ └── strings.xml │ ├── values-cs │ └── strings.xml │ ├── values-da-rDK │ └── strings.xml │ ├── values-el-rGR │ └── strings.xml │ ├── values-en-rUS │ └── strings.xml │ ├── values-es │ └── strings.xml │ ├── values-fa-rIR │ └── strings.xml │ ├── values-fr-rFR │ └── strings.xml │ ├── values-hu │ └── strings.xml │ ├── values-id │ └── strings.xml │ ├── values-it │ └── strings.xml │ ├── values-iw-rIL │ └── strings.xml │ ├── values-ja-rJP │ └── strings.xml │ ├── values-ko-rKR │ └── strings.xml │ ├── values-ml-rIN │ └── strings.xml │ ├── values-ne │ └── strings.xml │ ├── values-nl │ └── strings.xml │ ├── values-no-rNO │ └── strings.xml │ ├── values-or-rIN │ └── strings.xml │ ├── values-pa │ └── strings.xml │ ├── values-pl │ └── strings.xml │ ├── values-pt-rBR │ └── strings.xml │ ├── values-ro-rRO │ └── strings.xml │ ├── values-ru-rRU │ └── strings.xml │ ├── values-sr-rSP │ └── strings.xml │ ├── values-sv-rSE │ └── strings.xml │ ├── values-tr-rTR │ └── strings.xml │ ├── values-tr │ └── strings.xml │ ├── values-uk-rUA │ └── strings.xml │ ├── values-vi-rVN │ └── strings.xml │ ├── values-vi │ └── strings.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ ├── values │ ├── app_name.xml │ ├── ic_launcher_background.xml │ ├── strings.xml │ ├── styles.xml │ └── values.xml │ ├── xml-v25 │ └── shortcuts.xml │ └── xml │ ├── automotive_app_desc.xml │ ├── backup_rules.xml │ ├── data_extraction_rules.xml │ └── file_paths.xml ├── assets └── ic_launcher-playstore.png ├── build.gradle.kts ├── crowdin.yml ├── fastlane └── metadata │ └── android │ ├── en-US │ ├── full_description.txt │ ├── images │ │ ├── featureGraphic.png │ │ ├── icon.png │ │ └── phoneScreenshots │ │ │ ├── screenshot_1.png │ │ │ ├── screenshot_2.png │ │ │ ├── screenshot_3.png │ │ │ ├── screenshot_4.png │ │ │ ├── screenshot_5.png │ │ │ ├── screenshot_6.png │ │ │ └── screenshot_7.png │ ├── short_description.txt │ └── title.txt │ └── es-ES │ ├── full_description.txt │ ├── images │ ├── featureGraphic.png │ ├── icon.png │ └── phoneScreenshots │ │ ├── screenshot_1.png │ │ ├── screenshot_2.png │ │ ├── screenshot_3.png │ │ ├── screenshot_4.png │ │ ├── screenshot_5.png │ │ ├── screenshot_6.png │ │ └── screenshot_7.png │ ├── short_description.txt │ └── title.txt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── innertube ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── java │ └── com │ └── arturo254 │ └── innertube │ ├── InnerTube.kt │ ├── YouTube.kt │ ├── models │ ├── AccountInfo.kt │ ├── AutomixPreviewVideoRenderer.kt │ ├── Badges.kt │ ├── Button.kt │ ├── Context.kt │ ├── Continuation.kt │ ├── ContinuationItemRenderer.kt │ ├── Endpoint.kt │ ├── GridRenderer.kt │ ├── Icon.kt │ ├── Menu.kt │ ├── MusicCardShelfRenderer.kt │ ├── MusicCarouselShelfRenderer.kt │ ├── MusicDescriptionShelfRenderer.kt │ ├── MusicNavigationButtonRenderer.kt │ ├── MusicPlaylistShelfRenderer.kt │ ├── MusicQueueRenderer.kt │ ├── MusicResponsiveHeaderRenderer.kt │ ├── MusicResponsiveListItemRenderer.kt │ ├── MusicShelfRenderer.kt │ ├── MusicTwoRowItemRenderer.kt │ ├── NavigationEndpoint.kt │ ├── PlaylistDeleteBody.kt │ ├── PlaylistPanelRenderer.kt │ ├── PlaylistPanelVideoRenderer.kt │ ├── ResponseContext.kt │ ├── Runs.kt │ ├── SearchSuggestions.kt │ ├── SearchSuggestionsSectionRenderer.kt │ ├── SectionListRenderer.kt │ ├── SubscriptionButton.kt │ ├── Tabs.kt │ ├── ThumbnailRenderer.kt │ ├── Thumbnails.kt │ ├── YTItem.kt │ ├── YouTubeClient.kt │ ├── YouTubeLocale.kt │ ├── body │ │ ├── AccountMenuBody.kt │ │ ├── BrowseBody.kt │ │ ├── CreatePlaylistBody.kt │ │ ├── EditPlaylistBody.kt │ │ ├── GetQueueBody.kt │ │ ├── GetSearchSuggestionsBody.kt │ │ ├── GetTranscriptBody.kt │ │ ├── LikeBody.kt │ │ ├── NextBody.kt │ │ ├── PlayerBody.kt │ │ ├── SearchBody.kt │ │ └── SubscribeBody.kt │ └── response │ │ ├── AccountMenuResponse.kt │ │ ├── AddItemYouTubePlaylistResponse.kt │ │ ├── BrowseResponse.kt │ │ ├── ContinuationResponse.kt │ │ ├── CreatePlaylistResponse.kt │ │ ├── GetQueueResponse.kt │ │ ├── GetSearchSuggestionsResponse.kt │ │ ├── GetTranscriptResponse.kt │ │ ├── NextResponse.kt │ │ ├── PlayerResponse.kt │ │ └── SearchResponse.kt │ ├── pages │ ├── AlbumPage.kt │ ├── ArtistItemsContinuationPage.kt │ ├── ArtistItemsPage.kt │ ├── ArtistPage.kt │ ├── BrowseResult.kt │ ├── ExplorePage.kt │ ├── HistoryPage.kt │ ├── HomePage.kt │ ├── LibraryAlbumsPage.kt │ ├── LibraryContinuationPage.kt │ ├── LibraryPage.kt │ ├── MoodAndGenres.kt │ ├── NewPipe.kt │ ├── NewReleaseAlbumPage.kt │ ├── NextPage.kt │ ├── PageHelper.kt │ ├── PlaylistContinuationPage.kt │ ├── PlaylistPage.kt │ ├── RelatedPage.kt │ ├── SearchPage.kt │ ├── SearchSuggestionPage.kt │ └── SearchSummaryPage.kt │ └── utils │ └── Utils.kt ├── jossredconnect ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── com │ └── arturo254 │ └── jossredconnect │ └── JossRedClient.kt ├── kizzy ├── .gitignore ├── build.gradle.kts └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── my │ └── kizzy │ ├── gateway │ ├── DiscordWebSocket.kt │ └── entities │ │ ├── HeartBeat.kt │ │ ├── Identify.kt │ │ ├── Payload.kt │ │ ├── Ready.kt │ │ ├── Resume.kt │ │ ├── op │ │ ├── OpCode.kt │ │ └── OpCodesSerializer.kt │ │ └── presence │ │ ├── Activity.kt │ │ ├── Assets.kt │ │ ├── Metadata.kt │ │ ├── Presence.kt │ │ └── Timestamps.kt │ ├── remote │ ├── ApiResponse.kt │ └── ApiService.kt │ ├── repository │ └── KizzyRepository.kt │ ├── rpc │ ├── KizzyRPC.kt │ ├── RpcImage.kt │ └── UserInfo.kt │ └── utils │ └── Ext.kt ├── kugou ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── java │ └── com │ └── arturo254 │ └── kugou │ ├── KuGou.kt │ └── models │ ├── DownloadLyricsResponse.kt │ ├── Keyword.kt │ ├── SearchLyricsResponse.kt │ └── SearchSongResponse.kt ├── lint.xml ├── lrclib ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── java │ └── com │ └── arturo254 │ └── lrclib │ ├── LrcLib.kt │ └── models │ └── Track.kt ├── material-color-utilities ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── java │ └── com │ └── google │ └── material │ └── color │ ├── LICENSE │ ├── blend │ └── Blend.java │ ├── contrast │ └── Contrast.java │ ├── dislike │ └── DislikeAnalyzer.java │ ├── dynamiccolor │ ├── ContrastCurve.java │ ├── DynamicColor.java │ ├── DynamicScheme.java │ ├── MaterialDynamicColors.java │ ├── ToneDeltaPair.java │ ├── TonePolarity.java │ └── Variant.java │ ├── hct │ ├── Cam16.java │ ├── Hct.java │ ├── HctSolver.java │ └── ViewingConditions.java │ ├── palettes │ ├── CorePalette.java │ ├── CorePalettes.java │ └── TonalPalette.java │ ├── quantize │ ├── PointProvider.java │ ├── PointProviderLab.java │ ├── Quantizer.java │ ├── QuantizerCelebi.java │ ├── QuantizerMap.java │ ├── QuantizerResult.java │ ├── QuantizerWsmeans.java │ └── QuantizerWu.java │ ├── scheme │ ├── Scheme.java │ ├── SchemeContent.java │ ├── SchemeExpressive.java │ ├── SchemeFidelity.java │ ├── SchemeFruitSalad.java │ ├── SchemeMonochrome.java │ ├── SchemeNeutral.java │ ├── SchemeRainbow.java │ ├── SchemeTonalSpot.java │ └── SchemeVibrant.java │ ├── score │ └── Score.java │ ├── temperature │ └── TemperatureCache.java │ └── utils │ ├── ColorUtils.java │ ├── MathUtils.java │ └── StringUtils.java └── settings.gradle.kts /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/src/debug/res/values/app_name.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | OpenTune Debug 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/constants/HistorySource.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.constants 2 | 3 | enum class HistorySource { 4 | LOCAL, REMOTE 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/constants/LibraryFilter.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.constants 2 | 3 | enum class LibraryFilter { 4 | SONGS, 5 | ARTISTS, 6 | ALBUMS, 7 | PLAYLISTS, 8 | LIBRARY, 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/constants/MediaSessionConstants.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.constants 2 | 3 | import android.os.Bundle 4 | import androidx.media3.session.SessionCommand 5 | 6 | object MediaSessionConstants { 7 | const val ACTION_TOGGLE_LIBRARY = "TOGGLE_LIBRARY" 8 | const val ACTION_TOGGLE_LIKE = "TOGGLE_LIKE" 9 | const val ACTION_TOGGLE_SHUFFLE = "TOGGLE_SHUFFLE" 10 | const val ACTION_TOGGLE_REPEAT_MODE = "TOGGLE_REPEAT_MODE" 11 | val CommandToggleLibrary = SessionCommand(ACTION_TOGGLE_LIBRARY, Bundle.EMPTY) 12 | val CommandToggleLike = SessionCommand(ACTION_TOGGLE_LIKE, Bundle.EMPTY) 13 | val CommandToggleShuffle = SessionCommand(ACTION_TOGGLE_SHUFFLE, Bundle.EMPTY) 14 | val CommandToggleRepeatMode = SessionCommand(ACTION_TOGGLE_REPEAT_MODE, Bundle.EMPTY) 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/Converters.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db 2 | 3 | import androidx.room.TypeConverter 4 | import java.time.Instant 5 | import java.time.LocalDateTime 6 | import java.time.ZoneOffset 7 | 8 | class Converters { 9 | @TypeConverter 10 | fun fromTimestamp(value: Long?): LocalDateTime? = 11 | if (value != null) { 12 | LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC) 13 | } else { 14 | null 15 | } 16 | 17 | @TypeConverter 18 | fun dateToTimestamp(date: LocalDateTime?): Long? = 19 | date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli() 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/AlbumArtistMap.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.ForeignKey 6 | 7 | @Entity( 8 | tableName = "album_artist_map", 9 | primaryKeys = ["albumId", "artistId"], 10 | foreignKeys = [ 11 | ForeignKey( 12 | entity = AlbumEntity::class, 13 | parentColumns = ["id"], 14 | childColumns = ["albumId"], 15 | onDelete = ForeignKey.CASCADE, 16 | ), 17 | ForeignKey( 18 | entity = ArtistEntity::class, 19 | parentColumns = ["id"], 20 | childColumns = ["artistId"], 21 | onDelete = ForeignKey.CASCADE, 22 | ), 23 | ] 24 | ) 25 | data class AlbumArtistMap( 26 | @ColumnInfo(index = true) val albumId: String, 27 | @ColumnInfo(index = true) val artistId: String, 28 | val order: Int, 29 | ) 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/Artist.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.compose.runtime.Immutable 4 | import androidx.room.Embedded 5 | 6 | @Immutable 7 | data class Artist( 8 | @Embedded 9 | val artist: ArtistEntity, 10 | val timeListened: Int? = 0, 11 | ) : LocalItem() { 12 | override val id: String 13 | get() = artist.id 14 | override val title: String 15 | get() = artist.name 16 | override val thumbnailUrl: String? 17 | get() = artist.thumbnailUrl 18 | 19 | val songCount: Int 20 | get() = artist.songCount 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/Event.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.compose.runtime.Immutable 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.ForeignKey 7 | import androidx.room.PrimaryKey 8 | import java.time.LocalDateTime 9 | 10 | @Immutable 11 | @Entity( 12 | tableName = "event", 13 | foreignKeys = [ 14 | ForeignKey( 15 | entity = SongEntity::class, 16 | parentColumns = ["id"], 17 | childColumns = ["songId"], 18 | onDelete = ForeignKey.CASCADE, 19 | ), 20 | ], 21 | ) 22 | data class Event( 23 | @PrimaryKey(autoGenerate = true) val id: Long = 0, 24 | @ColumnInfo(index = true) val songId: String, 25 | val timestamp: LocalDateTime, 26 | val playTime: Long, 27 | ) 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/EventWithSong.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.compose.runtime.Immutable 4 | import androidx.room.Embedded 5 | import androidx.room.Relation 6 | 7 | @Immutable 8 | data class EventWithSong( 9 | @Embedded 10 | val event: Event, 11 | @Relation( 12 | entity = SongEntity::class, 13 | parentColumn = "songId", 14 | entityColumn = "id", 15 | ) 16 | val song: Song, 17 | ) 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/FormatEntity.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "format") 7 | data class FormatEntity( 8 | @PrimaryKey val id: String, 9 | val itag: Int, 10 | val mimeType: String, 11 | val codecs: String, 12 | val bitrate: Int, 13 | val sampleRate: Int?, 14 | val contentLength: Long, 15 | val loudnessDb: Double?, 16 | val playbackUrl: String? 17 | ) 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/LocalItem.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | sealed class LocalItem { 4 | abstract val id: String 5 | abstract val title: String 6 | abstract val thumbnailUrl: String? 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/LyricsEntity.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "lyrics") 7 | data class LyricsEntity( 8 | @PrimaryKey val id: String, 9 | val lyrics: String, 10 | ) { 11 | companion object { 12 | const val LYRICS_NOT_FOUND = "LYRICS_NOT_FOUND" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/PlayCountEntity.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.compose.runtime.Immutable 4 | import androidx.room.Entity 5 | 6 | @Immutable 7 | @Entity( 8 | tableName = "playCount", 9 | primaryKeys = ["song", "year", "month"] 10 | ) 11 | class PlayCountEntity( 12 | val song: String, // song id 13 | val year: Int = -1, 14 | val month: Int = -1, 15 | val count: Int = -1, 16 | ) 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/PlaylistSong.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.Embedded 4 | import androidx.room.Relation 5 | 6 | data class PlaylistSong( 7 | @Embedded val map: PlaylistSongMap, 8 | @Relation( 9 | parentColumn = "songId", 10 | entityColumn = "id", 11 | entity = SongEntity::class, 12 | ) 13 | val song: Song, 14 | ) 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/PlaylistSongMapPreview.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.DatabaseView 5 | 6 | @DatabaseView( 7 | viewName = "playlist_song_map_preview", 8 | value = "SELECT * FROM playlist_song_map WHERE position <= 3 ORDER BY position", 9 | ) 10 | data class PlaylistSongMapPreview( 11 | @ColumnInfo(index = true) val playlistId: String, 12 | @ColumnInfo(index = true) val songId: String, 13 | val idInPlaylist: Int = 0, 14 | ) 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/RelatedSongMap.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.ForeignKey 6 | import androidx.room.PrimaryKey 7 | 8 | @Entity( 9 | tableName = "related_song_map", 10 | foreignKeys = [ 11 | ForeignKey( 12 | entity = SongEntity::class, 13 | parentColumns = ["id"], 14 | childColumns = ["songId"], 15 | onDelete = ForeignKey.CASCADE, 16 | ), 17 | ForeignKey( 18 | entity = SongEntity::class, 19 | parentColumns = ["id"], 20 | childColumns = ["relatedSongId"], 21 | onDelete = ForeignKey.CASCADE, 22 | ), 23 | ], 24 | ) 25 | data class RelatedSongMap( 26 | @PrimaryKey(autoGenerate = true) val id: Long = 0, 27 | @ColumnInfo(index = true) val songId: String, 28 | @ColumnInfo(index = true) val relatedSongId: String, 29 | ) 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/SearchHistory.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.Index 5 | import androidx.room.PrimaryKey 6 | 7 | @Entity( 8 | tableName = "search_history", 9 | indices = [ 10 | Index( 11 | value = ["query"], 12 | unique = true, 13 | ), 14 | ], 15 | ) 16 | data class SearchHistory( 17 | @PrimaryKey(autoGenerate = true) val id: Long = 0, 18 | val query: String, 19 | ) 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/SetVideoIdEntity.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity(tableName = "set_video_id") 7 | data class SetVideoIdEntity( 8 | @PrimaryKey(autoGenerate = false) 9 | val videoId: String = "", 10 | val setVideoId: String? = null, 11 | ) 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/SongAlbumMap.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.ForeignKey 6 | 7 | @Entity( 8 | tableName = "song_album_map", 9 | primaryKeys = ["songId", "albumId"], 10 | foreignKeys = [ 11 | ForeignKey( 12 | entity = SongEntity::class, 13 | parentColumns = ["id"], 14 | childColumns = ["songId"], 15 | onDelete = ForeignKey.CASCADE, 16 | ), 17 | ForeignKey( 18 | entity = AlbumEntity::class, 19 | parentColumns = ["id"], 20 | childColumns = ["albumId"], 21 | onDelete = ForeignKey.CASCADE, 22 | ), 23 | ], 24 | ) 25 | data class SongAlbumMap( 26 | @ColumnInfo(index = true) val songId: String, 27 | @ColumnInfo(index = true) val albumId: String, 28 | val index: Int, 29 | ) 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/SongArtistMap.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.ForeignKey 6 | 7 | @Entity( 8 | tableName = "song_artist_map", 9 | primaryKeys = ["songId", "artistId"], 10 | foreignKeys = [ 11 | ForeignKey( 12 | entity = SongEntity::class, 13 | parentColumns = ["id"], 14 | childColumns = ["songId"], 15 | onDelete = ForeignKey.CASCADE, 16 | ), 17 | ForeignKey( 18 | entity = ArtistEntity::class, 19 | parentColumns = ["id"], 20 | childColumns = ["artistId"], 21 | onDelete = ForeignKey.CASCADE, 22 | ), 23 | ], 24 | ) 25 | data class SongArtistMap( 26 | @ColumnInfo(index = true) val songId: String, 27 | @ColumnInfo(index = true) val artistId: String, 28 | val position: Int, 29 | ) 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/SongWithStats.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Immutable 6 | data class SongWithStats( 7 | val id: String, 8 | val title: String, 9 | val thumbnailUrl: String, 10 | val songCountListened: Int, 11 | val timeListened: Long?, 12 | ) 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/SortedSongAlbumMap.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.DatabaseView 5 | 6 | @DatabaseView( 7 | viewName = "sorted_song_album_map", 8 | value = "SELECT * FROM song_album_map ORDER BY `index`", 9 | ) 10 | data class SortedSongAlbumMap( 11 | @ColumnInfo(index = true) val songId: String, 12 | @ColumnInfo(index = true) val albumId: String, 13 | val index: Int, 14 | ) 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/db/entities/SortedSongArtistMap.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.db.entities 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.DatabaseView 5 | 6 | @DatabaseView( 7 | viewName = "sorted_song_artist_map", 8 | value = "SELECT * FROM song_artist_map ORDER BY position", 9 | ) 10 | data class SortedSongArtistMap( 11 | @ColumnInfo(index = true) val songId: String, 12 | @ColumnInfo(index = true) val artistId: String, 13 | val position: Int, 14 | ) 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/extensions/CoroutineExt.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.extensions 2 | 3 | import kotlinx.coroutines.CoroutineExceptionHandler 4 | import kotlinx.coroutines.CoroutineScope 5 | import kotlinx.coroutines.flow.Flow 6 | import kotlinx.coroutines.flow.collectLatest 7 | import kotlinx.coroutines.launch 8 | 9 | fun Flow.collect( 10 | scope: CoroutineScope, 11 | action: suspend (value: T) -> Unit, 12 | ) { 13 | scope.launch { 14 | collect(action) 15 | } 16 | } 17 | 18 | fun Flow.collectLatest( 19 | scope: CoroutineScope, 20 | action: suspend (value: T) -> Unit, 21 | ) { 22 | scope.launch { 23 | collectLatest(action) 24 | } 25 | } 26 | 27 | val SilentHandler = CoroutineExceptionHandler { _, _ -> } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/extensions/FileExt.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.extensions 2 | 3 | import java.io.File 4 | import java.io.InputStream 5 | import java.io.OutputStream 6 | import java.util.zip.ZipInputStream 7 | import java.util.zip.ZipOutputStream 8 | 9 | operator fun File.div(child: String): File = File(this, child) 10 | 11 | fun InputStream.zipInputStream(): ZipInputStream = ZipInputStream(this) 12 | 13 | fun OutputStream.zipOutputStream(): ZipOutputStream = ZipOutputStream(this) 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/extensions/StringExt.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.extensions 2 | 3 | import androidx.sqlite.db.SimpleSQLiteQuery 4 | import java.net.InetSocketAddress 5 | import java.net.InetSocketAddress.createUnresolved 6 | 7 | inline fun > String?.toEnum(defaultValue: T): T = 8 | if (this == null) { 9 | defaultValue 10 | } else { 11 | try { 12 | enumValueOf(this) 13 | } catch (e: IllegalArgumentException) { 14 | defaultValue 15 | } 16 | } 17 | 18 | fun String.toSQLiteQuery(): SimpleSQLiteQuery = SimpleSQLiteQuery(this) 19 | 20 | fun String.toInetSocketAddress(): InetSocketAddress { 21 | val (host, port) = split(":") 22 | return createUnresolved(host, port.toInt()) 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/extensions/UtilExt.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.extensions 2 | 3 | fun tryOrNull(block: () -> T): T? = 4 | try { 5 | block() 6 | } catch (e: Exception) { 7 | null 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/lyrics/LyricsEntry.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.lyrics 2 | 3 | data class LyricsEntry( 4 | val time: Long, 5 | val text: String, 6 | ) : Comparable { 7 | override fun compareTo(other: LyricsEntry): Int = (time - other.time).toInt() 8 | 9 | companion object { 10 | val HEAD_LYRICS_ENTRY = LyricsEntry(0L, "") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/lyrics/LyricsProvider.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.lyrics 2 | 3 | import android.content.Context 4 | 5 | interface LyricsProvider { 6 | val name: String 7 | 8 | fun isEnabled(context: Context): Boolean 9 | 10 | suspend fun getLyrics( 11 | id: String, 12 | title: String, 13 | artist: String, 14 | duration: Int, 15 | ): Result 16 | 17 | suspend fun getAllLyrics( 18 | id: String, 19 | title: String, 20 | artist: String, 21 | duration: Int, 22 | callback: (String) -> Unit, 23 | ) { 24 | getLyrics(id, title, artist, duration).onSuccess(callback) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/lyrics/YouTubeLyricsProvider.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.lyrics 2 | 3 | import android.content.Context 4 | import com.arturo254.innertube.YouTube 5 | import com.arturo254.innertube.models.WatchEndpoint 6 | 7 | object YouTubeLyricsProvider : LyricsProvider { 8 | override val name = "YouTube Music" 9 | 10 | override fun isEnabled(context: Context) = true 11 | 12 | override suspend fun getLyrics( 13 | id: String, 14 | title: String, 15 | artist: String, 16 | duration: Int, 17 | ): Result = 18 | runCatching { 19 | val nextResult = YouTube.next(WatchEndpoint(videoId = id)).getOrThrow() 20 | YouTube 21 | .lyrics( 22 | endpoint = nextResult.lyricsEndpoint 23 | ?: throw IllegalStateException("Lyrics endpoint not found"), 24 | ).getOrThrow() ?: throw IllegalStateException("Lyrics unavailable") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/lyrics/YouTubeSubtitleLyricsProvider.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.lyrics 2 | 3 | import android.content.Context 4 | import com.arturo254.innertube.YouTube 5 | 6 | object YouTubeSubtitleLyricsProvider : LyricsProvider { 7 | override val name = "YouTube Subtitle" 8 | 9 | override fun isEnabled(context: Context) = true 10 | 11 | override suspend fun getLyrics( 12 | id: String, 13 | title: String, 14 | artist: String, 15 | duration: Int, 16 | ): Result = YouTube.transcript(id) 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/models/ItemsPage.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.models 2 | 3 | import com.arturo254.innertube.models.YTItem 4 | 5 | data class ItemsPage( 6 | val items: List, 7 | val continuation: String?, 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/models/PersistQueue.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.models 2 | 3 | import java.io.Serializable 4 | 5 | data class PersistQueue( 6 | val title: String?, 7 | val items: List, 8 | val mediaItemIndex: Int, 9 | val position: Long, 10 | ) : Serializable 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/models/SimilarRecommendation.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.models 2 | 3 | import com.arturo254.innertube.models.YTItem 4 | import com.arturo254.opentune.db.entities.LocalItem 5 | 6 | data class SimilarRecommendation( 7 | val title: LocalItem, 8 | val items: List, 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/playback/queues/EmptyQueue.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.playback.queues 2 | 3 | import androidx.media3.common.MediaItem 4 | import com.arturo254.opentune.models.MediaMetadata 5 | 6 | object EmptyQueue : Queue { 7 | override val preloadItem: MediaMetadata? = null 8 | 9 | override suspend fun getInitialStatus() = Queue.Status(null, emptyList(), -1) 10 | 11 | override fun hasNextPage() = false 12 | 13 | override suspend fun nextPage() = emptyList() 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/playback/queues/ListQueue.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.playback.queues 2 | 3 | import androidx.media3.common.MediaItem 4 | import com.arturo254.opentune.models.MediaMetadata 5 | 6 | class ListQueue( 7 | val title: String? = null, 8 | val items: List, 9 | val startIndex: Int = 0, 10 | val position: Long = 0L, 11 | ) : Queue { 12 | override val preloadItem: MediaMetadata? = null 13 | 14 | override suspend fun getInitialStatus() = Queue.Status(title, items, startIndex, position) 15 | 16 | override fun hasNextPage(): Boolean = false 17 | 18 | override suspend fun nextPage() = throw UnsupportedOperationException() 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/ui/component/shimmer/ButtonPlaceholder.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.ui.component.shimmer 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Spacer 5 | import androidx.compose.foundation.layout.height 6 | import androidx.compose.foundation.shape.RoundedCornerShape 7 | import androidx.compose.material3.ButtonDefaults 8 | import androidx.compose.material3.MaterialTheme 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.draw.clip 12 | 13 | @Composable 14 | fun ButtonPlaceholder(modifier: Modifier = Modifier) { 15 | Spacer( 16 | modifier 17 | .height(ButtonDefaults.MinHeight) 18 | .clip(RoundedCornerShape(50)) 19 | .background(MaterialTheme.colorScheme.onSurface), 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/ui/utils/ItemWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.ui.utils 2 | 3 | import androidx.compose.runtime.mutableStateOf 4 | 5 | class ItemWrapper( 6 | val item: T, 7 | ) { 8 | private val _isSelected = mutableStateOf(true) 9 | 10 | var isSelected: Boolean 11 | get() = _isSelected.value 12 | set(value) { 13 | _isSelected.value = value 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/ui/utils/NavControllerUtils.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.ui.utils 2 | 3 | import androidx.compose.ui.util.fastAny 4 | import androidx.navigation.NavController 5 | import com.arturo254.opentune.ui.screens.Screens 6 | 7 | val NavController.canNavigateUp: Boolean 8 | get() = currentBackStackEntry?.destination?.parent?.route != null 9 | 10 | fun NavController.backToMain() { 11 | while (canNavigateUp && !Screens.MainScreens.fastAny { it.route == currentBackStackEntry?.destination?.route }) { 12 | navigateUp() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/ui/utils/ShapeUtils.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.ui.utils 2 | 3 | import androidx.compose.foundation.shape.CornerBasedShape 4 | import androidx.compose.foundation.shape.CornerSize 5 | import androidx.compose.ui.unit.dp 6 | 7 | fun CornerBasedShape.top(): CornerBasedShape = 8 | copy(bottomStart = CornerSize(0.dp), bottomEnd = CornerSize(0.dp)) 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/ui/utils/StringUtils.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.ui.utils 2 | 3 | import kotlin.math.absoluteValue 4 | 5 | fun formatFileSize(sizeBytes: Long): String { 6 | val prefix = if (sizeBytes < 0) "-" else "" 7 | var result: Long = sizeBytes.absoluteValue 8 | var suffix = "B" 9 | if (result > 900) { 10 | suffix = "KB" 11 | result /= 1024 12 | } 13 | if (result > 900) { 14 | suffix = "MB" 15 | result /= 1024 16 | } 17 | if (result > 900) { 18 | suffix = "GB" 19 | result /= 1024 20 | } 21 | if (result > 900) { 22 | suffix = "TB" 23 | result /= 1024 24 | } 25 | if (result > 900) { 26 | suffix = "PB" 27 | result /= 1024 28 | } 29 | return "$prefix$result $suffix" 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/ui/utils/YouTubeUtils.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.ui.utils 2 | 3 | fun String.resize( 4 | width: Int? = null, 5 | height: Int? = null, 6 | ): String { 7 | if (width == null && height == null) return this 8 | "https://lh3\\.googleusercontent\\.com/.*=w(\\d+)-h(\\d+).*".toRegex() 9 | .matchEntire(this)?.groupValues?.let { group -> 10 | val (W, H) = group.drop(1).map { it.toInt() } 11 | var w = width 12 | var h = height 13 | if (w != null && h == null) h = (w / W) * H 14 | if (w == null && h != null) w = (h / H) * W 15 | return "${split("=w")[0]}=w$w-h$h-p-l90-rj" 16 | } 17 | if (this matches "https://yt3\\.ggpht\\.com/.*=s(\\d+)".toRegex()) { 18 | return "$this-s${width ?: height}" 19 | } 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/utils/NetworkUtils.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.utils 2 | 3 | import android.content.Context 4 | import android.net.ConnectivityManager 5 | import android.net.NetworkCapabilities 6 | import androidx.core.content.getSystemService 7 | 8 | fun isInternetAvailable(context: Context): Boolean { 9 | val connectivityManager = context.getSystemService() ?: return false 10 | val activeNetwork = connectivityManager.activeNetwork ?: return false 11 | val networkCapabilities = 12 | connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false 13 | 14 | return when { 15 | networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true 16 | networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true 17 | networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true 18 | else -> false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/utils/Updater.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.utils 2 | 3 | import io.ktor.client.HttpClient 4 | import io.ktor.client.request.get 5 | import io.ktor.client.statement.bodyAsText 6 | import org.json.JSONObject 7 | 8 | object Updater { 9 | private val client = HttpClient() 10 | var lastCheckTime = -1L 11 | private set 12 | 13 | suspend fun getLatestVersionName(): Result = 14 | runCatching { 15 | val response = 16 | client.get("https://api.github.com/repos/Arturo254/OpenTune/releases/latest") 17 | .bodyAsText() 18 | val json = JSONObject(response) 19 | val versionName = json.getString("name") 20 | lastCheckTime = System.currentTimeMillis() 21 | versionName 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/utils/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.utils 2 | 3 | fun reportException(throwable: Throwable) { 4 | throwable.printStackTrace() 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/utils/potoken/PoTokenException.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.utils.potoken 2 | 3 | class PoTokenException(message: String) : Exception(message) 4 | 5 | // to be thrown if the WebView provided by the system is broken 6 | class BadWebViewException(message: String) : Exception(message) 7 | 8 | fun buildExceptionForJsError(error: String): Exception { 9 | return if (error.contains("SyntaxError")) 10 | BadWebViewException(error) 11 | else 12 | PoTokenException(error) 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/arturo254/opentune/utils/potoken/PoTokenResult.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.opentune.utils.potoken 2 | 3 | class PoTokenResult( 4 | val playerRequestPoToken: String, 5 | val streamingDataPoToken: String, 6 | ) -------------------------------------------------------------------------------- /app/src/main/logoxd-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/logoxd-playstore.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/album.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_back.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_downward.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_forward.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_top_left.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_upward.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/artist.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/attach_money.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/backup.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bedtime.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/block.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bookmark.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bookmark_filled.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cached.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/car.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/casino.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/check.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/check_box.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/check_circle.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/chevron_right.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/clear_all.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/close.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/codigo.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/compare_arrows.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/content_copy.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/contrast.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/dark_mode.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/delete.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/delete_history.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/deployed_code_update.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/desktop_windows.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/discord.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/discover_tune.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/donate.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/done.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/double_arrow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/download.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/drag_handle.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/email.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/equalizer.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/error.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/expand_less.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/expand_more.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/explicit.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/explore.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/explore_filled.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/extension.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fast_forward.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/favorite.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/favorite_border.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/feedback.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/format_align_center.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/format_align_left.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/format_color.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/google.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/gradient.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/graphic_eq.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/grid_view.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/group.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/history.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/home.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/home_filled.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/home_outlined.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ia_icon.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/image.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/info.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/input.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/liberapay.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/library_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/library_add_check.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/library_music.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/library_music_filled.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/library_music_outlined.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/license.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/lightbulb.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/line_curve.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/link.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/location_on.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/lock.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/lock_open.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/login.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/logout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/manage_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/menu.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/more_horiz.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/more_vert.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/music_note.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/nav_bar.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/navigate_next.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notification_off.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notification_on.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notifications_off.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/offline.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pause.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/person.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/play.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/playlist_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/playlist_import.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/playlist_play.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/previewalbum.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/drawable/previewalbum.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/queue_music.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/radar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/drawable/radar.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/radio.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/radio_button_unchecked.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/remove.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/repeat.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/repeat_on.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/replay.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/resource_public.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/restore.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/robot.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/schedule.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search_off.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/security.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/select_all.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shortcut_albums.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shortcut_explore.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shortcut_library.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shortcut_playlists.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shortcut_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shortcut_songs.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shuffle.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shuffle_on.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/signal_cellular_nodata.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/similar.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/skip_next.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/skip_previous.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sliders.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/slow_motion_video.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/storage.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/swipe.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sync.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/thumb_up.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/token.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/translate.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/trending_up.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tune.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/uncheck_box.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/update.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/verified_user.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/volume_up.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/wifi_proxy.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-hdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /app/src/main/res/values/app_name.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | OpenTune 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @drawable/play 5 | @drawable/pause 6 | @drawable/skip_previous 7 | @drawable/skip_next 8 | -------------------------------------------------------------------------------- /app/src/main/res/xml/automotive_app_desc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 11 | 14 | 17 | 18 | 19 | 22 | 25 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 12 | 13 | 14 | 17 | 18 | 19 | 22 | -------------------------------------------------------------------------------- /assets/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/assets/ic_launcher-playstore.png -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /app/src/main/res/values/strings.xml 3 | translation: /app/src/main/res/values-%android_code%/strings.xml 4 | -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/full_description.txt: -------------------------------------------------------------------------------- 1 | A YouTube Music client with Material Design 3, for Android. 2 | 3 | Features: 4 | 5 | - Ad-free playback 6 | - Background playback 7 | - Advanced search 8 | - Integrated login 9 | - Library management 10 | - Offline mode 11 | - Synchronized lyrics 12 | - Silence skipping 13 | - Audio normalization 14 | - Tempo and pitch control 15 | - Dynamic theme 16 | - Multi-language support 17 | - Android Auto support 18 | - Material Design 3 19 | - Download covers 20 | - Customize playlist minuatures 21 | - Add a custom Avatar -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/featureGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/featureGraphic.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/icon.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_1.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_2.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_3.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_4.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_5.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_6.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/en-US/images/phoneScreenshots/screenshot_7.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/short_description.txt: -------------------------------------------------------------------------------- 1 | A YouTube Music client with Material Design 3, for Android -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/title.txt: -------------------------------------------------------------------------------- 1 | OpenTune -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/full_description.txt: -------------------------------------------------------------------------------- 1 | Un cliente de YouTube Music con Material Design 3, para Android. 2 | 3 | Características: 4 | 5 | - Reproducción sin anuncios 6 | - Reproducción en segundo plano 7 | - Búsqueda avanzada 8 | - Inicio de sesión integrado 9 | - Gestión de bibliotecas 10 | - Modo sin conexión 11 | - Letras sincronizadas 12 | - Salto de silencio 13 | - Normalización de audio 14 | - Control de tempo y tono 15 | - Tema dinámico 16 | - Soporte multilingüe 17 | - Compatibilidad con Android Auto 18 | - Material Design 3 19 | - Descarga de carátulas 20 | - Personalizar miniaturas de listas de reproducción 21 | - Añadir un avatar personalizado -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/featureGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/featureGraphic.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/icon.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_1.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_2.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_3.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_4.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_5.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_6.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/fastlane/metadata/android/es-ES/images/phoneScreenshots/screenshot_7.png -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/short_description.txt: -------------------------------------------------------------------------------- 1 | Un cliente de YouTube Music con Material Design 3, para Android -------------------------------------------------------------------------------- /fastlane/metadata/android/es-ES/title.txt: -------------------------------------------------------------------------------- 1 | OpenTune -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arturo254/OpenTune/313cc617c17a510623fb262b671eed3e4cdacda4/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 16 19:56:51 CST 2025 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /innertube/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /innertube/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | @Suppress("DSL_SCOPE_VIOLATION") 4 | alias(libs.plugins.kotlin.serialization) 5 | } 6 | 7 | kotlin { 8 | jvmToolchain(17) 9 | } 10 | 11 | dependencies { 12 | implementation(libs.ktor.client.core) 13 | implementation(libs.ktor.client.okhttp) 14 | implementation(libs.ktor.client.content.negotiation) 15 | implementation(libs.ktor.serialization.json) 16 | implementation(libs.ktor.client.encoding) 17 | implementation(libs.brotli) 18 | implementation(libs.newpipe.extractor) 19 | testImplementation(libs.junit) 20 | } 21 | -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/AccountInfo.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | data class AccountInfo( 4 | val name: String, 5 | val email: String?, 6 | val channelHandle: String?, 7 | ) 8 | -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/AutomixPreviewVideoRenderer.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class AutomixPreviewVideoRenderer( 7 | val content: Content, 8 | ) { 9 | @Serializable 10 | data class Content( 11 | val automixPlaylistVideoRenderer: AutomixPlaylistVideoRenderer, 12 | ) { 13 | @Serializable 14 | data class AutomixPlaylistVideoRenderer( 15 | val navigationEndpoint: NavigationEndpoint, 16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/Badges.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class Badges( 7 | val musicInlineBadgeRenderer: MusicInlineBadgeRenderer?, 8 | ) { 9 | @Serializable 10 | data class MusicInlineBadgeRenderer( 11 | val icon: Icon, 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/Button.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class Button( 7 | val buttonRenderer: ButtonRenderer, 8 | ) { 9 | @Serializable 10 | data class ButtonRenderer( 11 | val text: Runs, 12 | val navigationEndpoint: NavigationEndpoint?, 13 | val command: NavigationEndpoint?, 14 | val icon: Icon?, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/Continuation.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.ExperimentalSerializationApi 4 | import kotlinx.serialization.Serializable 5 | import kotlinx.serialization.json.JsonNames 6 | 7 | @OptIn(ExperimentalSerializationApi::class) 8 | @Serializable 9 | data class Continuation( 10 | @JsonNames("nextContinuationData", "nextRadioContinuationData") 11 | val nextContinuationData: NextContinuationData?, 12 | ) { 13 | @Serializable 14 | data class NextContinuationData( 15 | val continuation: String, 16 | ) 17 | } 18 | 19 | fun List.getContinuation() = 20 | firstOrNull()?.nextContinuationData?.continuation -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/ContinuationItemRenderer.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class ContinuationItemRenderer( 7 | val continuationEndpoint: ContinuationEndpoint?, 8 | ) { 9 | @Serializable 10 | data class ContinuationEndpoint( 11 | val continuationCommand: ContinuationCommand?, 12 | ) { 13 | @Serializable 14 | data class ContinuationCommand( 15 | val token: String?, 16 | ) 17 | } 18 | } -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/GridRenderer.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class GridRenderer( 7 | val header: Header?, 8 | val items: List, 9 | val continuations: List?, 10 | ) { 11 | @Serializable 12 | data class Header( 13 | val gridHeaderRenderer: GridHeaderRenderer, 14 | ) { 15 | @Serializable 16 | data class GridHeaderRenderer( 17 | val title: Runs, 18 | ) 19 | } 20 | 21 | @Serializable 22 | data class Item( 23 | val musicNavigationButtonRenderer: MusicNavigationButtonRenderer?, 24 | val musicTwoRowItemRenderer: MusicTwoRowItemRenderer?, 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/Icon.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class Icon( 7 | val iconType: String, 8 | ) 9 | -------------------------------------------------------------------------------- /innertube/src/main/java/com/arturo254/innertube/models/MusicCardShelfRenderer.kt: -------------------------------------------------------------------------------- 1 | package com.arturo254.innertube.models 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class MusicCardShelfRenderer( 7 | val title: Runs, 8 | val subtitle: Runs, 9 | val thumbnail: ThumbnailRenderer, 10 | val header: Header, 11 | val contents: List?, 12 | val buttons: List