├── .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