From 724f743627c5ea912d99de1b285e73cd0a4a9517 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 26 Feb 2020 22:19:24 +0530 Subject: [PATCH] Code refactor and Flat, Fit, Full, Circle theme toolbar shadow fixes --- app/build.gradle | 6 +- app/src/main/assets/index.html | 5 +- app/src/main/assets/retro-changelog.html | 2 +- .../java/code/name/monkey/retromusic/App.kt | 10 +- .../code/name/monkey/retromusic/Constants.kt | 32 +- .../retromusic/activities/AboutActivity.kt | 21 +- .../activities/AlbumDetailsActivity.kt | 43 +- .../activities/ArtistDetailActivity.kt | 43 +- .../activities/DriveModeActivity.kt | 27 +- .../activities/GenreDetailsActivity.kt | 10 +- .../activities/LicenseActivity.java | 14 +- .../activities/LockScreenActivity.kt | 13 +- .../retromusic/activities/LyricsActivity.kt | 29 +- .../retromusic/activities/MainActivity.java | 67 +-- .../activities/PlayingQueueActivity.kt | 4 +- .../activities/PlaylistDetailActivity.kt | 9 +- .../retromusic/activities/PurchaseActivity.kt | 4 +- .../retromusic/activities/SearchActivity.kt | 26 +- .../retromusic/activities/SettingsActivity.kt | 9 +- .../activities/ShareInstagramStory.kt | 19 +- .../activities/WhatsNewActivity.java | 44 +- .../base/AbsMusicServiceActivity.kt | 17 +- .../base/AbsSlidingMusicPanelActivity.kt | 48 +- .../activities/base/AbsThemeActivity.kt | 11 +- .../activities/bugreport/BugReportActivity.kt | 16 +- .../bugreport/model/DeviceInfo.java | 5 +- .../activities/saf/SAFGuideActivity.java | 5 +- .../tageditor/AbsTagEditorActivity.kt | 5 +- .../tageditor/AlbumTagEditorActivity.kt | 19 +- .../tageditor/SongTagEditorActivity.kt | 23 +- .../tageditor/WriteTagsAsyncTask.java | 67 ++- .../adapter/CategoryInfoAdapter.java | 37 +- .../retromusic/adapter/ContributorAdapter.kt | 1 - .../adapter/base/AbsMultiSelectAdapter.java | 16 +- .../adapter/base/MediaEntryViewHolder.java | 5 +- .../adapter/playlist/PlaylistAdapter.kt | 5 +- .../adapter/song/AbsOffsetSongAdapter.kt | 3 +- .../song/OrderablePlaylistSongAdapter.kt | 3 +- .../adapter/song/PlayingQueueAdapter.kt | 11 +- .../appshortcuts/AppShortcutIconGenerator.kt | 104 ++-- .../AppShortcutLauncherActivity.kt | 111 ++-- .../appshortcuts/DynamicShortcutManager.kt | 76 +-- .../shortcuttype/BaseShortcutType.kt | 46 +- .../shortcuttype/LastAddedShortcutType.kt | 35 +- .../shortcuttype/SearchShortCutType.kt | 31 +- .../shortcuttype/ShuffleAllShortcutType.kt | 31 +- .../shortcuttype/TopTracksShortcutType.kt | 31 +- .../retromusic/appwidgets/AppWidgetBig.kt | 129 ++--- .../retromusic/appwidgets/AppWidgetCard.kt | 402 ++++++------- .../retromusic/appwidgets/AppWidgetClassic.kt | 25 +- .../retromusic/appwidgets/AppWidgetSmall.kt | 133 +++-- .../retromusic/appwidgets/AppWidgetText.kt | 249 ++++---- .../retromusic/appwidgets/BootReceiver.kt | 58 +- .../appwidgets/base/BaseAppWidget.kt | 277 ++++----- .../retromusic/dagger/MusicComponent.kt | 13 +- .../dagger/module/PresenterModile.kt | 12 +- .../retromusic/deezer/DeezerApiService.kt | 2 +- .../retromusic/dialogs/AddToPlaylistDialog.kt | 7 +- .../dialogs/BlacklistFolderChooserDialog.kt | 6 +- .../dialogs/CreatePlaylistDialog.kt | 10 +- .../dialogs/DeletePlaylistDialog.kt | 2 +- .../dialogs/DeleteSongsAsyncTask.java | 69 +-- .../retromusic/dialogs/DeleteSongsDialog.kt | 8 +- .../dialogs/OptionsSheetDialogFragment.kt | 6 +- .../dialogs/RenamePlaylistDialog.kt | 11 +- .../retromusic/dialogs/SleepTimerDialog.kt | 12 +- .../retromusic/dialogs/SongDetailDialog.kt | 24 +- .../retromusic/dialogs/SongShareDialog.kt | 5 +- .../retromusic/fragments/AlbumCoverStyle.kt | 10 +- .../fragments/MiniPlayerFragment.kt | 18 +- .../retromusic/fragments/VolumeFragment.kt | 14 +- .../fragments/base/AbsMusicServiceFragment.kt | 5 +- .../base/AbsPlayerControlsFragment.kt | 9 +- .../fragments/base/AbsPlayerFragment.kt | 37 +- .../fragments/mainactivity/AlbumsFragment.kt | 6 +- .../fragments/mainactivity/ArtistsFragment.kt | 4 +- .../mainactivity/BannerHomeFragment.kt | 43 +- .../mainactivity/FoldersFragment.java | 534 +++++++++--------- .../fragments/mainactivity/GenresFragment.kt | 1 + .../mainactivity/PlayingQueueFragment.kt | 12 +- .../mainactivity/PlaylistsFragment.kt | 3 +- .../fragments/mainactivity/SongsFragment.kt | 5 +- .../player/PlayerAlbumCoverFragment.kt | 11 +- .../player/adaptive/AdaptiveFragment.kt | 26 +- .../AdaptivePlaybackControlsFragment.kt | 40 +- .../blur/BlurPlaybackControlsFragment.kt | 25 +- .../player/blur/BlurPlayerFragment.kt | 6 +- .../fragments/player/card/CardFragment.kt | 2 +- .../card/CardPlaybackControlsFragment.kt | 43 +- .../player/cardblur/CardBlurFragment.kt | 6 +- .../CardBlurPlaybackControlsFragment.kt | 27 +- .../player/circle/CirclePlayerFragment.kt | 30 +- .../fragments/player/color/ColorFragment.kt | 77 +-- .../fragments/player/fit/FitFragment.kt | 2 +- .../player/flat/FlatPlayerFragment.kt | 3 +- .../player/full/FullPlayerFragment.kt | 32 +- .../LockScreenPlayerControlsFragment.kt | 27 +- .../player/material/MaterialFragment.kt | 2 +- .../fragments/player/normal/PlayerFragment.kt | 42 +- .../player/peak/PeakPlayerFragment.kt | 12 +- .../player/plain/PlainPlayerFragment.kt | 4 +- .../simple/SimplePlaybackControlsFragment.kt | 32 +- .../player/simple/SimplePlayerFragment.kt | 2 +- .../tiny/TinyPlaybackControlsFragment.kt | 25 +- .../fragments/settings/AbsSettingsFragment.kt | 14 +- .../settings/MainSettingsFragment.kt | 41 +- .../settings/NotificationSettingsFragment.kt | 18 +- .../settings/NowPlayingSettingsFragment.kt | 3 +- .../settings/PersonalizeSettingsFragment.kt | 6 +- .../settings/ThemeSettingsFragment.kt | 18 +- .../retromusic/glide/AlbumGlideRequest.java | 53 +- .../retromusic/glide/ArtistGlideRequest.java | 60 +- .../retromusic/glide/BlurTransformation.kt | 14 +- .../glide/RetroMusicColoredTarget.kt | 15 +- .../retromusic/glide/RetroMusicGlideModule.kt | 7 +- .../retromusic/glide/SongGlideRequest.java | 51 +- .../glide/artistimage/ArtistImageLoader.kt | 22 +- .../audiocover/AudioFileCoverLoader.java | 1 - .../glide/palette/BitmapPaletteWrapper.java | 1 + .../helper/HorizontalAdapterHelper.kt | 8 +- .../retromusic/helper/MusicPlayerRemote.kt | 33 +- .../retromusic/helper/SearchQueryHelper.kt | 32 +- .../monkey/retromusic/helper/StackBlur.java | 12 +- .../retromusic/helper/menu/GenreMenuHelper.kt | 2 +- .../helper/menu/PlaylistMenuHelper.kt | 29 +- .../retromusic/helper/menu/SongMenuHelper.kt | 3 +- .../retromusic/helper/menu/SongsMenuHelper.kt | 12 +- .../monkey/retromusic/loaders/AlbumLoader.kt | 53 +- .../monkey/retromusic/loaders/ArtistLoader.kt | 4 +- .../monkey/retromusic/loaders/GenreLoader.kt | 27 +- .../loaders/LastAddedSongsLoader.kt | 9 +- .../retromusic/loaders/PlaylistLoader.kt | 2 +- .../retromusic/loaders/PlaylistSongsLoader.kt | 3 +- .../monkey/retromusic/loaders/SearchLoader.kt | 2 +- .../monkey/retromusic/loaders/SongLoader.kt | 2 +- .../retromusic/loaders/SortedCursor.java | 1 + .../retromusic/loaders/SortedLongCursor.java | 1 + .../TopAndRecentlyPlayedTracksLoader.kt | 2 +- .../monkey/retromusic/lyrics/LrcHelper.java | 8 +- .../name/monkey/retromusic/lyrics/LrcView.kt | 146 +++-- .../misc/AsyncSearchResultLoader.kt | 3 +- .../misc/CustomFragmentStatePagerAdapter.java | 8 +- .../retromusic/misc/DialogAsyncTask.java | 1 + ...teToastMediaScannerCompletionListener.java | 13 +- .../retromusic/misc/WeakContextAsyncTask.kt | 2 +- .../retromusic/misc/WrappedAsyncTaskLoader.kt | 2 +- .../retromusic/model/AbsCustomPlaylist.java | 5 +- .../name/monkey/retromusic/model/Album.kt | 2 +- .../name/monkey/retromusic/model/Artist.kt | 2 +- .../monkey/retromusic/model/CategoryInfo.java | 69 ++- .../monkey/retromusic/model/Playlist.java | 5 +- .../monkey/retromusic/model/PlaylistSong.java | 29 +- .../retromusic/model/lyrics/Lyrics.java | 14 +- .../model/smartplaylist/AbsSmartPlaylist.java | 2 + .../model/smartplaylist/HistoryPlaylist.java | 8 +- .../smartplaylist/LastAddedPlaylist.java | 8 +- .../smartplaylist/MyTopTracksPlaylist.java | 8 +- .../smartplaylist/ShuffleAllPlaylist.java | 8 +- .../mvp/presenter/AlbumDetailsPresenter.kt | 6 +- .../mvp/presenter/AlbumPresenter.kt | 6 +- .../mvp/presenter/ArtistDetailsPresenter.kt | 8 +- .../mvp/presenter/ArtistPresenter.kt | 6 +- .../mvp/presenter/GenreDetailsPresenter.kt | 6 +- .../mvp/presenter/GenrePresenter.kt | 6 +- .../retromusic/mvp/presenter/HomePresenter.kt | 6 +- .../mvp/presenter/PlaylistPresenter.kt | 6 +- .../mvp/presenter/PlaylistSongsPresenter.kt | 6 +- .../mvp/presenter/SearchPresenter.kt | 6 +- .../retromusic/mvp/presenter/SongPresenter.kt | 6 +- .../AlbumCoverStylePreferenceDialog.kt | 25 +- .../preferences/BlacklistPreferenceDialog.kt | 7 +- .../preferences/LibraryPreference.kt | 20 +- .../NowPlayingScreenPreferenceDialog.kt | 29 +- .../retromusic/providers/HistoryStore.java | 1 + .../providers/MusicPlaybackQueueStore.java | 25 +- .../retromusic/providers/RepositoryImpl.kt | 29 +- .../providers/interfaces/Repository.kt | 7 +- .../retromusic/rest/LastFMRestClient.java | 15 +- .../retromusic/rest/model/LastFmAlbum.java | 142 +++-- .../retromusic/rest/model/LastFmArtist.java | 71 ++- .../service/MediaButtonIntentReceiver.kt | 13 +- .../service/MediaSessionCallback.kt | 5 +- .../retromusic/service/MediaStoreObserver.kt | 4 +- .../retromusic/service/MultiPlayer.java | 5 +- .../retromusic/service/MusicService.java | 363 +++++------- .../retromusic/service/PlaybackHandler.java | 22 +- .../retromusic/service/QueueSaveHandler.kt | 4 +- .../service/ThrottledSeekHandler.kt | 4 +- .../notification/PlayingNotification.kt | 13 +- .../notification/PlayingNotificationImpl.kt | 154 +++-- .../notification/PlayingNotificationOreo.kt | 221 +++++--- .../transform/ParallaxPagerTransformer.kt | 1 - .../retromusic/util/ArtistSignatureUtil.java | 1 + .../retromusic/util/CustomArtistImageUtil.kt | 99 ++-- .../monkey/retromusic/util/MusicUtil.java | 24 +- .../retromusic/util/NavigationUtil.java | 25 +- .../monkey/retromusic/util/PlaylistsUtil.java | 37 +- .../retromusic/util/PreferenceUtil.java | 82 ++- .../retromusic/util/RetroColorUtil.java | 2 - .../monkey/retromusic/util/RetroUtil.java | 11 +- .../monkey/retromusic/util/RingtoneManager.kt | 12 +- .../retromusic/util/SwipeAndDragHelper.java | 2 +- .../monkey/retromusic/util/ThemeManager.kt | 21 +- .../name/monkey/retromusic/util/ViewUtil.kt | 10 +- .../views/BaselineGridTextView.java | 5 +- .../views/BottomNavigationBarTinted.kt | 12 +- .../retromusic/views/BreadCrumbLayout.java | 250 ++++---- .../retromusic/views/CircularImageView.java | 3 +- .../retromusic/views/ContributorsView.java | 1 + .../monkey/retromusic/views/ListItemView.kt | 6 +- .../views/MetalRecyclerViewPager.kt | 15 +- .../retromusic/views/PopupBackground.java | 14 +- ...ollingViewOnApplyWindowInsetsListener.java | 1 + .../name/monkey/retromusic/views/SeekArc.java | 95 ++-- .../volume/AudioVolumeContentObserver.java | 5 +- .../volume/AudioVolumeObserver.java | 1 + .../res/drawable-hdpi/default_album_art.webp | Bin 5936 -> 4522 bytes .../res/drawable-hdpi/default_artist_art.webp | Bin 4062 -> 2692 bytes .../res/drawable-hdpi/default_audio_art.webp | Bin 2748 -> 1444 bytes .../res/drawable-mdpi/default_album_art.webp | Bin 3538 -> 2390 bytes .../res/drawable-mdpi/default_artist_art.webp | Bin 2410 -> 1762 bytes .../res/drawable-mdpi/default_audio_art.webp | Bin 1546 -> 932 bytes .../drawable-v21/widget_selector_light.xml | 2 +- .../res/drawable-xhdpi/default_album_art.webp | Bin 8320 -> 5526 bytes .../drawable-xhdpi/default_artist_art.webp | Bin 6056 -> 3732 bytes .../res/drawable-xhdpi/default_audio_art.webp | Bin 4188 -> 1964 bytes .../drawable-xxhdpi/default_album_art.webp | Bin 14094 -> 9048 bytes .../drawable-xxhdpi/default_artist_art.webp | Bin 10834 -> 5794 bytes .../drawable-xxhdpi/default_audio_art.webp | Bin 8136 -> 3252 bytes .../drawable-xxxhdpi/default_album_art.webp | Bin 21488 -> 12568 bytes .../drawable-xxxhdpi/default_artist_art.webp | Bin 16950 -> 8084 bytes .../drawable-xxxhdpi/default_audio_art.webp | Bin 13032 -> 4588 bytes app/src/main/res/drawable/circle_progress.xml | 40 +- .../drawable/ic_app_shortcut_background.xml | 4 +- .../drawable/ic_app_shortcut_shuffle_all.xml | 4 +- .../drawable/ic_app_shortcut_top_tracks.xml | 4 +- .../drawable/ic_arrow_forward_white_24dp.xml | 10 +- .../drawable/ic_bookmark_music_white_24dp.xml | 4 +- .../drawable/ic_card_giftcard_white_24dp.xml | 3 +- .../res/drawable/ic_clear_all_black_24dp.xml | 3 +- .../main/res/drawable/ic_close_white_24dp.xml | 3 +- .../res/drawable/ic_cookie_white_24dp.xml | 10 +- .../res/drawable/ic_dashboard_white_24dp.xml | 13 +- .../drawable/ic_drag_vertical_white_24dp.xml | 4 +- .../res/drawable/ic_drive_eta_white_24dp.xml | 13 +- .../main/res/drawable/ic_edit_white_24dp.xml | 3 +- .../main/res/drawable/ic_flag_white_24dp.xml | 3 +- .../res/drawable/ic_folder_white_24dp.xml | 3 +- .../drawable/ic_github_circle_white_24dp.xml | 4 +- .../res/drawable/ic_guitar_white_24dp.xml | 3 +- .../main/res/drawable/ic_help_white_24dp.xml | 3 +- .../drawable/ic_library_add_white_24dp.xml | 3 +- .../main/res/drawable/ic_mic_white_24dp.xml | 3 +- app/src/main/res/drawable/ic_person_flat.xml | 32 +- .../res/drawable/ic_play_arrow_white_24dp.xml | 3 +- .../main/res/drawable/ic_save_white_24dp.xml | 3 +- .../res/drawable/ic_search_white_24dp.xml | 13 +- .../ic_skip_previous_round_white_32dp.xml | 3 +- .../main/res/drawable/ic_sort_white_24dp.xml | 3 +- .../main/res/drawable/ic_telegram_white.xml | 10 +- .../res/drawable/ic_testing_white_24dp.xml | 2 +- .../res/drawable/ic_twitter_white_24dp.xml | 10 +- .../res/drawable/ic_volume_up_white_24dp.xml | 3 +- app/src/main/res/drawable/line_button.xml | 10 +- app/src/main/res/drawable/shadow_down.xml | 4 +- .../main/res/drawable/shadow_down_strong.xml | 4 +- app/src/main/res/drawable/shadow_up.xml | 4 +- .../main/res/drawable/shadow_up_edited.xml | 4 +- app/src/main/res/drawable/square_window.xml | 2 +- app/src/main/res/drawable/widget_selector.xml | 8 +- .../res/drawable/widget_selector_light.xml | 8 +- .../main/res/layout-land/activity_album.xml | 6 +- .../layout-land/activity_album_tag_editor.xml | 4 +- .../main/res/layout-land/fragment_blur.xml | 2 +- .../res/layout-land/fragment_card_player.xml | 74 +-- .../layout-land/fragment_circle_player.xml | 2 +- .../res/layout-xlarge/activity_user_info.xml | 4 +- app/src/main/res/layout/activity_album.xml | 9 +- .../res/layout/activity_artist_content.xml | 4 +- .../res/layout/activity_artist_details.xml | 2 +- .../main/res/layout/activity_drive_mode.xml | 2 +- app/src/main/res/layout/activity_license.xml | 2 +- .../main/res/layout/activity_main_content.xml | 6 +- .../main/res/layout/app_widget_classic.xml | 164 +++--- app/src/main/res/layout/card_credit.xml | 2 +- ...ment_adaptive_player_playback_controls.xml | 10 +- .../main/res/layout/fragment_card_player.xml | 66 +-- ...fragment_card_player_playback_controls.xml | 2 +- .../res/layout/fragment_circle_player.xml | 2 +- ...ragment_color_player_playback_controls.xml | 2 +- app/src/main/res/layout/fragment_fit.xml | 2 + ...fragment_flat_player_playback_controls.xml | 2 +- .../fragment_main_activity_recycler_view.xml | 2 +- .../layout/fragment_peak_control_player.xml | 2 +- app/src/main/res/layout/item_artist_card.xml | 4 +- app/src/main/res/layout/item_contributor.xml | 2 +- .../res/layout/item_contributor_header.xml | 6 +- .../res/layout/item_list_quick_actions.xml | 3 +- .../main/res/menu/menu_playlist_detail.xml | 2 +- app/src/main/res/menu/menu_search.xml | 4 +- .../res/mipmap-anydpi-v26/ic_launcher.xml | 4 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 4 +- app/src/main/res/values/contributor_attrs.xml | 3 +- app/src/main/res/values/lrc_view_attrs.xml | 3 +- 304 files changed, 3874 insertions(+), 3524 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index db468026..c1c507b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,7 +15,7 @@ proguardDictionaries { android { compileSdkVersion 29 buildToolsVersion = '29.0.2' - + defaultConfig { minSdkVersion 21 targetSdkVersion 29 @@ -24,8 +24,8 @@ android { vectorDrawables.useSupportLibrary = true applicationId "code.name.monkey.retromusic" - versionCode 411 - versionName '3.4.950' + versionCode 413 + versionName '3.4.970' multiDexEnabled true diff --git a/app/src/main/assets/index.html b/app/src/main/assets/index.html index 4d858fba..037d52fa 100644 --- a/app/src/main/assets/index.html +++ b/app/src/main/assets/index.html @@ -2,8 +2,8 @@ - - diff --git a/app/src/main/assets/retro-changelog.html b/app/src/main/assets/retro-changelog.html index 2e173e32..8717202f 100644 --- a/app/src/main/assets/retro-changelog.html +++ b/app/src/main/assets/retro-changelog.html @@ -1 +1 @@ -

v3.4.950

v3.4.900

v3.4.850

v3.4.800

v3.4.700

v3.4.600

v3.4.500

If you see entire app white or dark or black select same theme in settings to fix

FAQ's

*If you face any UI related issues you clear app data and cache, if its not working try to uninstall and install again.

\ No newline at end of file +

v3.4.970

v3.4.900

v3.4.850

v3.4.800

v3.4.700

v3.4.600

v3.4.500

If you see entire app white or dark or black select same theme in settings to fix

FAQ's

*If you face any UI related issues you clear app data and cache, if its not working try to uninstall and install again.

\ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/App.kt b/app/src/main/java/code/name/monkey/retromusic/App.kt index e00eeb31..afabc12b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/App.kt +++ b/app/src/main/java/code/name/monkey/retromusic/App.kt @@ -51,7 +51,11 @@ class App : MultiDexApplication() { override fun onProductPurchased(productId: String, details: TransactionDetails?) {} override fun onPurchaseHistoryRestored() { - Toast.makeText(this@App, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG) + Toast.makeText( + this@App, + R.string.restored_previous_purchase_please_restart, + Toast.LENGTH_LONG + ) .show() } @@ -79,7 +83,9 @@ class App : MultiDexApplication() { } fun isProVersion(): Boolean { - return BuildConfig.DEBUG || instance?.billingProcessor!!.isPurchased(PRO_VERSION_PRODUCT_ID) + return BuildConfig.DEBUG || instance?.billingProcessor!!.isPurchased( + PRO_VERSION_PRODUCT_ID + ) } lateinit var musicComponent: MusicComponent diff --git a/app/src/main/java/code/name/monkey/retromusic/Constants.kt b/app/src/main/java/code/name/monkey/retromusic/Constants.kt index 3da9b547..0b3c6fa9 100644 --- a/app/src/main/java/code/name/monkey/retromusic/Constants.kt +++ b/app/src/main/java/code/name/monkey/retromusic/Constants.kt @@ -19,7 +19,8 @@ import android.provider.MediaStore object Constants { - const val RATE_ON_GOOGLE_PLAY = "https://play.google.com/store/apps/details?id=code.name.monkey.retromusic" + const val RATE_ON_GOOGLE_PLAY = + "https://play.google.com/store/apps/details?id=code.name.monkey.retromusic" const val TRANSLATE = "http://monkeycodeapp.oneskyapp.com/collaboration/project?id=238534" const val GITHUB_PROJECT = "https://github.com/h4h13/RetroMusicPlayer" const val TELEGRAM_CHANGE_LOG = "https://t.me/retromusiclog" @@ -31,19 +32,22 @@ object Constants { const val FAQ_LINK = "https://github.com/h4h13/RetroMusicPlayer/blob/master/FAQ.md" const val PINTEREST = "https://in.pinterest.com/retromusicapp/" - const val BASE_SELECTION = MediaStore.Audio.AudioColumns.IS_MUSIC + "=1" + " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''" + const val BASE_SELECTION = + MediaStore.Audio.AudioColumns.IS_MUSIC + "=1" + " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''" - val baseProjection = arrayOf(BaseColumns._ID, // 0 - MediaStore.Audio.AudioColumns.TITLE, // 1 - MediaStore.Audio.AudioColumns.TRACK, // 2 - MediaStore.Audio.AudioColumns.YEAR, // 3 - MediaStore.Audio.AudioColumns.DURATION, // 4 - MediaStore.Audio.AudioColumns.DATA, // 5 - MediaStore.Audio.AudioColumns.DATE_MODIFIED, // 6 - MediaStore.Audio.AudioColumns.ALBUM_ID, // 7 - MediaStore.Audio.AudioColumns.ALBUM, // 8 - MediaStore.Audio.AudioColumns.ARTIST_ID, // 9 - MediaStore.Audio.AudioColumns.ARTIST,// 10 - MediaStore.Audio.AudioColumns.COMPOSER)// 11 + val baseProjection = arrayOf( + BaseColumns._ID, // 0 + MediaStore.Audio.AudioColumns.TITLE, // 1 + MediaStore.Audio.AudioColumns.TRACK, // 2 + MediaStore.Audio.AudioColumns.YEAR, // 3 + MediaStore.Audio.AudioColumns.DURATION, // 4 + MediaStore.Audio.AudioColumns.DATA, // 5 + MediaStore.Audio.AudioColumns.DATE_MODIFIED, // 6 + MediaStore.Audio.AudioColumns.ALBUM_ID, // 7 + MediaStore.Audio.AudioColumns.ALBUM, // 8 + MediaStore.Audio.AudioColumns.ARTIST_ID, // 9 + MediaStore.Audio.AudioColumns.ARTIST,// 10 + MediaStore.Audio.AudioColumns.COMPOSER + )// 11 const val NUMBER_OF_TOP_TRACKS = 99 } diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/AboutActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/AboutActivity.kt index 21e44354..bc1b8506 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/AboutActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/AboutActivity.kt @@ -32,22 +32,11 @@ import com.afollestad.materialdialogs.bottomsheets.BottomSheet import com.afollestad.materialdialogs.list.listItems import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import kotlinx.android.synthetic.main.activity_about.toolbar -import kotlinx.android.synthetic.main.card_credit.recyclerView -import kotlinx.android.synthetic.main.card_other.changelog -import kotlinx.android.synthetic.main.card_other.openSource -import kotlinx.android.synthetic.main.card_other.version -import kotlinx.android.synthetic.main.card_retro_info.appGithub -import kotlinx.android.synthetic.main.card_retro_info.appRate -import kotlinx.android.synthetic.main.card_retro_info.appShare -import kotlinx.android.synthetic.main.card_retro_info.appTranslation -import kotlinx.android.synthetic.main.card_retro_info.bugReportLink -import kotlinx.android.synthetic.main.card_retro_info.donateLink -import kotlinx.android.synthetic.main.card_retro_info.faqLink -import kotlinx.android.synthetic.main.card_social.instagramLink -import kotlinx.android.synthetic.main.card_social.pinterestLink -import kotlinx.android.synthetic.main.card_social.telegramLink -import kotlinx.android.synthetic.main.card_social.twitterLink +import kotlinx.android.synthetic.main.activity_about.* +import kotlinx.android.synthetic.main.card_credit.* +import kotlinx.android.synthetic.main.card_other.* +import kotlinx.android.synthetic.main.card_retro_info.* +import kotlinx.android.synthetic.main.card_social.* import java.io.IOException import java.nio.charset.StandardCharsets diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/AlbumDetailsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/AlbumDetailsActivity.kt index 02466a3f..569ffc73 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/AlbumDetailsActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/AlbumDetailsActivity.kt @@ -30,7 +30,6 @@ import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.glide.AlbumGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.RetroMusicColoredTarget -import code.name.monkey.retromusic.glide.SongGlideRequest import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder import code.name.monkey.retromusic.interfaces.CabHolder @@ -39,31 +38,12 @@ import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsView import code.name.monkey.retromusic.rest.model.LastFmAlbum -import code.name.monkey.retromusic.util.MusicUtil -import code.name.monkey.retromusic.util.NavigationUtil -import code.name.monkey.retromusic.util.PreferenceUtil -import code.name.monkey.retromusic.util.RetroColorUtil -import code.name.monkey.retromusic.util.RetroUtil +import code.name.monkey.retromusic.util.* import com.afollestad.materialcab.MaterialCab import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.activity_album.albumCoverContainer -import kotlinx.android.synthetic.main.activity_album.albumText -import kotlinx.android.synthetic.main.activity_album.albumTitle -import kotlinx.android.synthetic.main.activity_album.image -import kotlinx.android.synthetic.main.activity_album.toolbar -import kotlinx.android.synthetic.main.activity_album_content.aboutAlbumText -import kotlinx.android.synthetic.main.activity_album_content.aboutAlbumTitle -import kotlinx.android.synthetic.main.activity_album_content.listeners -import kotlinx.android.synthetic.main.activity_album_content.listenersLabel -import kotlinx.android.synthetic.main.activity_album_content.moreRecyclerView -import kotlinx.android.synthetic.main.activity_album_content.moreTitle -import kotlinx.android.synthetic.main.activity_album_content.playAction -import kotlinx.android.synthetic.main.activity_album_content.recyclerView -import kotlinx.android.synthetic.main.activity_album_content.scrobbles -import kotlinx.android.synthetic.main.activity_album_content.scrobblesLabel -import kotlinx.android.synthetic.main.activity_album_content.shuffleAction -import kotlinx.android.synthetic.main.activity_album_content.songTitle -import java.util.ArrayList +import kotlinx.android.synthetic.main.activity_album.* +import kotlinx.android.synthetic.main.activity_album_content.* +import java.util.* import javax.inject.Inject import android.util.Pair as UtilPair @@ -127,7 +107,8 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) { intent.extras?.getInt(EXTRA_ALBUM_ID)?.let { albumDetailsPresenter.loadAlbum(it) - albumCoverContainer?.transitionName = "${getString(R.string.transition_album_art)}_$it" + albumCoverContainer?.transitionName = + "${getString(R.string.transition_album_art)}_$it" } } else { finish() @@ -357,7 +338,8 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C R.id.action_sort_order_title -> sortOrder = AlbumSongSortOrder.SONG_A_Z R.id.action_sort_order_title_desc -> sortOrder = AlbumSongSortOrder.SONG_Z_A R.id.action_sort_order_track_list -> sortOrder = AlbumSongSortOrder.SONG_TRACK_LIST - R.id.action_sort_order_artist_song_duration -> sortOrder = AlbumSongSortOrder.SONG_DURATION + R.id.action_sort_order_artist_song_duration -> sortOrder = + AlbumSongSortOrder.SONG_DURATION } if (sortOrder != null) { item.isChecked = true @@ -368,9 +350,12 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C private fun setUpSortOrderMenu(sortOrder: SubMenu) { when (savedSortOrder) { - AlbumSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title).isChecked = true - AlbumSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc).isChecked = true - AlbumSongSortOrder.SONG_TRACK_LIST -> sortOrder.findItem(R.id.action_sort_order_track_list).isChecked = + AlbumSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title) + .isChecked = true + AlbumSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc) + .isChecked = true + AlbumSongSortOrder.SONG_TRACK_LIST -> sortOrder.findItem(R.id.action_sort_order_track_list) + .isChecked = true AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration) .isChecked = true diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/ArtistDetailActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/ArtistDetailActivity.kt index 30a80ee0..8575ce82 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/ArtistDetailActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/ArtistDetailActivity.kt @@ -33,32 +33,14 @@ import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView import code.name.monkey.retromusic.rest.model.LastFmArtist -import code.name.monkey.retromusic.util.CustomArtistImageUtil -import code.name.monkey.retromusic.util.MusicUtil -import code.name.monkey.retromusic.util.PreferenceUtil -import code.name.monkey.retromusic.util.RetroColorUtil -import code.name.monkey.retromusic.util.RetroUtil +import code.name.monkey.retromusic.util.* import com.afollestad.materialcab.MaterialCab import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.activity_artist_content.albumRecyclerView -import kotlinx.android.synthetic.main.activity_artist_content.albumTitle -import kotlinx.android.synthetic.main.activity_artist_content.biographyText -import kotlinx.android.synthetic.main.activity_artist_content.biographyTitle -import kotlinx.android.synthetic.main.activity_artist_content.listeners -import kotlinx.android.synthetic.main.activity_artist_content.listenersLabel -import kotlinx.android.synthetic.main.activity_artist_content.playAction -import kotlinx.android.synthetic.main.activity_artist_content.recyclerView -import kotlinx.android.synthetic.main.activity_artist_content.scrobbles -import kotlinx.android.synthetic.main.activity_artist_content.scrobblesLabel -import kotlinx.android.synthetic.main.activity_artist_content.shuffleAction -import kotlinx.android.synthetic.main.activity_artist_content.songTitle -import kotlinx.android.synthetic.main.activity_artist_details.artistCoverContainer -import kotlinx.android.synthetic.main.activity_artist_details.artistTitle -import kotlinx.android.synthetic.main.activity_artist_details.image -import kotlinx.android.synthetic.main.activity_artist_details.text -import kotlinx.android.synthetic.main.activity_artist_details.toolbar -import java.util.Locale +import kotlinx.android.synthetic.main.activity_artist_content.* +import kotlinx.android.synthetic.main.activity_artist_details.* +import java.util.* import javax.inject.Inject +import kotlin.collections.ArrayList class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, CabHolder { override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab { @@ -238,8 +220,10 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, scrobbles.show() scrobblesLabel.show() - listeners.text = RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat()) - scrobbles.text = RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat()) + listeners.text = + RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat()) + scrobbles.text = + RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat()) } } } @@ -318,9 +302,14 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, return true } R.id.action_reset_artist_image -> { - Toast.makeText(this@ArtistDetailActivity, resources.getString(R.string.updating), Toast.LENGTH_SHORT) + Toast.makeText( + this@ArtistDetailActivity, + resources.getString(R.string.updating), + Toast.LENGTH_SHORT + ) .show() - CustomArtistImageUtil.getInstance(this@ArtistDetailActivity).resetCustomArtistImage(artist) + CustomArtistImageUtil.getInstance(this@ArtistDetailActivity) + .resetCustomArtistImage(artist) forceDownload = true return true } diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt index 7b5ceef6..633bf0fd 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt @@ -35,19 +35,7 @@ import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.MusicUtil import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.activity_drive_mode.close -import kotlinx.android.synthetic.main.activity_drive_mode.image -import kotlinx.android.synthetic.main.activity_drive_mode.nextButton -import kotlinx.android.synthetic.main.activity_drive_mode.playPauseButton -import kotlinx.android.synthetic.main.activity_drive_mode.previousButton -import kotlinx.android.synthetic.main.activity_drive_mode.progressSlider -import kotlinx.android.synthetic.main.activity_drive_mode.repeatButton -import kotlinx.android.synthetic.main.activity_drive_mode.shuffleButton -import kotlinx.android.synthetic.main.activity_drive_mode.songCurrentProgress -import kotlinx.android.synthetic.main.activity_drive_mode.songFavourite -import kotlinx.android.synthetic.main.activity_drive_mode.songText -import kotlinx.android.synthetic.main.activity_drive_mode.songTitle -import kotlinx.android.synthetic.main.activity_drive_mode.songTotalTime +import kotlinx.android.synthetic.main.activity_drive_mode.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -96,7 +84,8 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback { private fun toggleFavourite() { CoroutineScope(Dispatchers.IO).launch { - val isFavourite = MusicUtil.isFavorite(this@DriveModeActivity, MusicPlayerRemote.currentSong) + val isFavourite = + MusicUtil.isFavorite(this@DriveModeActivity, MusicPlayerRemote.currentSong) withContext(Dispatchers.Main) { songFavourite.setImageResource(if (isFavourite) R.drawable.ic_favorite_white_24dp else R.drawable.ic_favorite_border_white_24dp) } @@ -183,7 +172,10 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> shuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -191,7 +183,10 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + repeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/GenreDetailsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/GenreDetailsActivity.kt index d3e2de87..3f57ac58 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/GenreDetailsActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/GenreDetailsActivity.kt @@ -21,11 +21,8 @@ import code.name.monkey.retromusic.mvp.presenter.GenreDetailsView import code.name.monkey.retromusic.util.DensityUtil import code.name.monkey.retromusic.util.RetroColorUtil import com.afollestad.materialcab.MaterialCab -import kotlinx.android.synthetic.main.activity_playlist_detail.empty -import kotlinx.android.synthetic.main.activity_playlist_detail.emptyEmoji -import kotlinx.android.synthetic.main.activity_playlist_detail.recyclerView -import kotlinx.android.synthetic.main.activity_playlist_detail.toolbar -import java.util.ArrayList +import kotlinx.android.synthetic.main.activity_playlist_detail.* +import java.util.* import javax.inject.Inject /** @@ -134,7 +131,8 @@ class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDet override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab { if (cab != null && cab!!.isActive) cab?.finish() - cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes).setCloseDrawableRes(R.drawable.ic_close_white_24dp) + cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes) + .setCloseDrawableRes(R.drawable.ic_close_white_24dp) .setBackgroundColor( RetroColorUtil.shiftBackgroundColorForLightText( ATHUtil.resolveColor( diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.java index 11881b94..d2117129 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.java +++ b/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.java @@ -18,19 +18,23 @@ import android.graphics.Color; import android.os.Bundle; import android.view.MenuItem; import android.webkit.WebView; + import androidx.annotation.NonNull; import androidx.appcompat.widget.Toolbar; + +import org.jetbrains.annotations.Nullable; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + import code.name.monkey.appthemehelper.ThemeStore; import code.name.monkey.appthemehelper.util.ATHUtil; import code.name.monkey.appthemehelper.util.ColorUtil; import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper; import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.activities.base.AbsBaseActivity; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import org.jetbrains.annotations.Nullable; /** * Created by hemanths on 2019-09-27. diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt index f2e2bc98..5af09dfe 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt @@ -18,7 +18,7 @@ import com.r0adkll.slidr.Slidr import com.r0adkll.slidr.model.SlidrConfig import com.r0adkll.slidr.model.SlidrListener import com.r0adkll.slidr.model.SlidrPosition -import kotlinx.android.synthetic.main.activity_lock_screen.image +import kotlinx.android.synthetic.main.activity_lock_screen.* class LockScreenActivity : AbsMusicServiceActivity() { private var fragment: LockScreenPlayerControlsFragment? = null @@ -29,9 +29,11 @@ class LockScreenActivity : AbsMusicServiceActivity() { setShowWhenLocked(true) setTurnScreenOn(true) } else { - this.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or - WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or - WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) + this.window.addFlags( + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or + WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + ) } setDrawUnderStatusBar() setContentView(R.layout.activity_lock_screen) @@ -53,7 +55,8 @@ class LockScreenActivity : AbsMusicServiceActivity() { override fun onSlideClosed(): Boolean { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager + val keyguardManager = + getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager keyguardManager.requestDismissKeyguard(this@LockScreenActivity, null) } finish() diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt index 9dc03ef9..06b59f87 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt @@ -8,11 +8,7 @@ import android.os.Build import android.os.Bundle import android.text.InputType import android.text.TextUtils -import android.view.LayoutInflater -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import android.view.WindowManager +import android.view.* import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment @@ -20,13 +16,8 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentStatePagerAdapter import androidx.viewpager.widget.ViewPager import code.name.monkey.appthemehelper.ThemeStore -import code.name.monkey.appthemehelper.util.ATHUtil +import code.name.monkey.appthemehelper.util.* import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor -import code.name.monkey.appthemehelper.util.ColorUtil -import code.name.monkey.appthemehelper.util.MaterialUtil -import code.name.monkey.appthemehelper.util.MaterialValueHelper -import code.name.monkey.appthemehelper.util.TintHelper -import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.retromusic.App import code.name.monkey.retromusic.R import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity @@ -47,17 +38,17 @@ import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.bottomsheets.BottomSheet import com.afollestad.materialdialogs.input.getInputLayout import com.afollestad.materialdialogs.input.input -import kotlinx.android.synthetic.main.activity_lyrics.fab -import kotlinx.android.synthetic.main.activity_lyrics.tabs -import kotlinx.android.synthetic.main.activity_lyrics.toolbar -import kotlinx.android.synthetic.main.activity_lyrics.viewPager -import kotlinx.android.synthetic.main.fragment_lyrics.offlineLyrics -import kotlinx.android.synthetic.main.fragment_synced.lyricsView +import kotlinx.android.synthetic.main.activity_lyrics.* +import kotlinx.android.synthetic.main.fragment_lyrics.* +import kotlinx.android.synthetic.main.fragment_synced.* import org.jaudiotagger.tag.FieldKey import java.io.File -import java.util.EnumMap +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.set -class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPager.OnPageChangeListener { +class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, + ViewPager.OnPageChangeListener { override fun onPageScrollStateChanged(state: Int) { when (state) { ViewPager.SCROLL_STATE_IDLE -> fab.show() diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java index e8f80904..aa2db905 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java +++ b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java @@ -33,11 +33,25 @@ import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; + import androidx.annotation.NonNull; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.transition.TransitionManager; + +import com.afollestad.materialcab.MaterialCab; +import com.afollestad.materialcab.MaterialCab.Callback; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.card.MaterialCardView; +import com.google.android.material.textview.MaterialTextView; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + import code.name.monkey.appthemehelper.util.ATHUtil; import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper; import code.name.monkey.retromusic.R; @@ -47,12 +61,12 @@ import code.name.monkey.retromusic.dialogs.OptionsSheetDialogFragment; import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment; import code.name.monkey.retromusic.fragments.mainactivity.AlbumsFragment; import code.name.monkey.retromusic.fragments.mainactivity.ArtistsFragment; +import code.name.monkey.retromusic.fragments.mainactivity.BannerHomeFragment; +import code.name.monkey.retromusic.fragments.mainactivity.FoldersFragment; import code.name.monkey.retromusic.fragments.mainactivity.GenresFragment; import code.name.monkey.retromusic.fragments.mainactivity.PlayingQueueFragment; import code.name.monkey.retromusic.fragments.mainactivity.PlaylistsFragment; import code.name.monkey.retromusic.fragments.mainactivity.SongsFragment; -import code.name.monkey.retromusic.fragments.mainactivity.FoldersFragment; -import code.name.monkey.retromusic.fragments.mainactivity.BannerHomeFragment; import code.name.monkey.retromusic.helper.MusicPlayerRemote; import code.name.monkey.retromusic.helper.SearchQueryHelper; import code.name.monkey.retromusic.helper.SortOrder.AlbumSortOrder; @@ -70,15 +84,6 @@ import code.name.monkey.retromusic.util.NavigationUtil; import code.name.monkey.retromusic.util.PreferenceUtil; import code.name.monkey.retromusic.util.RetroColorUtil; import code.name.monkey.retromusic.util.RetroUtil; -import com.afollestad.materialcab.MaterialCab; -import com.afollestad.materialcab.MaterialCab.Callback; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.card.MaterialCardView; -import com.google.android.material.textview.MaterialTextView; -import java.util.ArrayList; -import java.util.List; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * Created by hemanths on 2020-02-19. @@ -91,18 +96,6 @@ public class MainActivity extends AbsSlidingMusicPanelActivity public static final int APP_INTRO_REQUEST = 100; public static final String EXPAND_PANEL = "expand_panel"; - - @Nullable - MainActivityFragmentCallbacks currentFragment; - - private boolean blockRequestPermissions = false; - - private MaterialCab cab; - - private AppBarLayout mAppBarLayout; - - private MaterialTextView mAppTitle; - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { @@ -117,11 +110,14 @@ public class MainActivity extends AbsSlidingMusicPanelActivity } } }; - private final IntentFilter mIntentFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF); - + @Nullable + MainActivityFragmentCallbacks currentFragment; + private boolean blockRequestPermissions = false; + private MaterialCab cab; + private AppBarLayout mAppBarLayout; + private MaterialTextView mAppTitle; private Toolbar mToolbar; - private MaterialCardView mToolbarContainer; @Override @@ -298,7 +294,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity @Override public void onSharedPreferenceChanged(final @NonNull SharedPreferences sharedPreferences, - final @NonNull String key) { + final @NonNull String key) { if (key.equals(PreferenceUtil.GENERAL_THEME) || key.equals(PreferenceUtil.BLACK_THEME) || key.equals(PreferenceUtil.ADAPTIVE_COLOR_APP) || key.equals(PreferenceUtil.DOMINANT_COLOR) || key.equals(PreferenceUtil.USER_NAME) || key.equals(PreferenceUtil.TOGGLE_FULL_SCREEN) || @@ -344,22 +340,14 @@ public class MainActivity extends AbsSlidingMusicPanelActivity } if (!tag.equals(currentTag)) { - getSupportFragmentManager().beginTransaction() + getSupportFragmentManager() + .beginTransaction() .replace(R.id.fragment_container, fragment, tag) .commit(); currentFragment = (MainActivityFragmentCallbacks) fragment; } } - public void setMusicChooser(final int option) { - PreferenceUtil.getInstance(this).setLastMusicChooser(option); - if (option == OptionsSheetDialogFragment.FOLDER) { - setCurrentFragment(FoldersFragment.newInstance(this), FoldersFragment.TAG); - } else { - selectedFragment(PreferenceUtil.getInstance(this).getLastPage()); - } - } - @NotNull @Override protected View createContentView() { @@ -591,7 +579,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity } private long parseIdFromIntent(@NonNull Intent intent, String longKey, - String stringKey) { + String stringKey) { long id = intent.getLongExtra(longKey, -1); if (id < 0) { String idString = intent.getStringExtra(stringKey); @@ -641,8 +629,9 @@ public class MainActivity extends AbsSlidingMusicPanelActivity } } + private void setUpGridSizeMenu(@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment, - @NonNull SubMenu gridSizeMenu) { + @NonNull SubMenu gridSizeMenu) { switch (fragment.getGridSize()) { case 1: diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt index 4af72c3a..d68e2b96 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt @@ -19,9 +19,7 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropM import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils -import kotlinx.android.synthetic.main.activity_playing_queue.clearQueue -import kotlinx.android.synthetic.main.activity_playing_queue.recyclerView -import kotlinx.android.synthetic.main.activity_playing_queue.toolbar +import kotlinx.android.synthetic.main.activity_playing_queue.* open class PlayingQueueActivity : AbsMusicServiceActivity() { diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PlaylistDetailActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PlaylistDetailActivity.kt index ab22a62e..4541ecb5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/PlaylistDetailActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/PlaylistDetailActivity.kt @@ -28,11 +28,7 @@ import com.afollestad.materialcab.MaterialCab import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils -import kotlinx.android.synthetic.main.activity_playlist_detail.empty -import kotlinx.android.synthetic.main.activity_playlist_detail.emptyEmoji -import kotlinx.android.synthetic.main.activity_playlist_detail.emptyText -import kotlinx.android.synthetic.main.activity_playlist_detail.recyclerView -import kotlinx.android.synthetic.main.activity_playlist_detail.toolbar +import kotlinx.android.synthetic.main.activity_playlist_detail.* import javax.inject.Inject class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, PlaylistSongsView { @@ -148,7 +144,8 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli if (cab != null && cab!!.isActive) { cab!!.finish() } - cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes).setCloseDrawableRes(R.drawable.ic_close_white_24dp) + cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes) + .setCloseDrawableRes(R.drawable.ic_close_white_24dp) .setBackgroundColor( RetroColorUtil.shiftBackgroundColorForLightText( ATHUtil.resolveColor( diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt index 07c1ee04..f2a5ee8e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt @@ -14,9 +14,7 @@ import code.name.monkey.retromusic.R import code.name.monkey.retromusic.activities.base.AbsBaseActivity import com.anjlab.android.iab.v3.BillingProcessor import com.anjlab.android.iab.v3.TransactionDetails -import kotlinx.android.synthetic.main.activity_pro_version.purchaseButton -import kotlinx.android.synthetic.main.activity_pro_version.restoreButton -import kotlinx.android.synthetic.main.activity_pro_version.toolbar +import kotlinx.android.synthetic.main.activity_pro_version.* import java.lang.ref.WeakReference class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler { diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/SearchActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/SearchActivity.kt index 850aaae3..494b6dd5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/SearchActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/SearchActivity.kt @@ -29,17 +29,12 @@ import code.name.monkey.retromusic.mvp.presenter.SearchPresenter import code.name.monkey.retromusic.mvp.presenter.SearchView import code.name.monkey.retromusic.util.RetroUtil import com.google.android.material.textfield.TextInputEditText -import kotlinx.android.synthetic.main.activity_search.appBarLayout -import kotlinx.android.synthetic.main.activity_search.back -import kotlinx.android.synthetic.main.activity_search.clearText -import kotlinx.android.synthetic.main.activity_search.empty -import kotlinx.android.synthetic.main.activity_search.keyboardPopup -import kotlinx.android.synthetic.main.activity_search.recyclerView -import kotlinx.android.synthetic.main.activity_search.searchContainer -import kotlinx.android.synthetic.main.activity_search.searchView -import kotlinx.android.synthetic.main.activity_search.voiceSearch -import java.util.Locale +import kotlinx.android.synthetic.main.activity_search.* +import java.util.* import javax.inject.Inject +import kotlin.collections.ArrayList +import kotlin.collections.MutableList +import kotlin.collections.emptyList class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher, SearchView { @Inject @@ -71,7 +66,8 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch back.setOnClickListener { onBackPressed() } voiceSearch.setOnClickListener { startMicSearch() } clearText.setOnClickListener { searchView.clearText() } - searchContainer.backgroundTintList = ColorStateList.valueOf(ATHUtil.resolveColor(this, R.attr.colorSurface)) + searchContainer.backgroundTintList = + ColorStateList.valueOf(ATHUtil.resolveColor(this, R.attr.colorSurface)) keyboardPopup.setOnClickListener { val inputManager = getSystemService(Service.INPUT_METHOD_SERVICE) as InputMethodManager @@ -80,7 +76,10 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch keyboardPopup.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this)) ColorStateList.valueOf( - MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(ThemeStore.accentColor(this))) + MaterialValueHelper.getPrimaryTextColor( + this, + ColorUtil.isColorLight(ThemeStore.accentColor(this)) + ) ).apply { keyboardPopup.setTextColor(this) keyboardPopup.iconTint = this @@ -175,7 +174,8 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch when (requestCode) { REQ_CODE_SPEECH_INPUT -> { if (resultCode == Activity.RESULT_OK && null != data) { - val result: ArrayList? = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS) + val result: ArrayList? = + data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS) query = result?.get(0) searchView.setText(query, BufferType.EDITABLE) searchPresenter.search(query!!) diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/SettingsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/SettingsActivity.kt index 8a7568db..a788e567 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/SettingsActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/SettingsActivity.kt @@ -4,14 +4,12 @@ import android.os.Bundle import android.view.MenuItem import androidx.annotation.StringRes import androidx.fragment.app.Fragment -import androidx.transition.TransitionManager import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.retromusic.R import code.name.monkey.retromusic.activities.base.AbsBaseActivity import code.name.monkey.retromusic.fragments.settings.MainSettingsFragment -import kotlinx.android.synthetic.main.activity_settings.appBarLayout -import kotlinx.android.synthetic.main.activity_settings.toolbar +import kotlinx.android.synthetic.main.activity_settings.* class SettingsActivity : AbsBaseActivity() { @@ -28,7 +26,8 @@ class SettingsActivity : AbsBaseActivity() { setupToolbar() if (savedInstanceState == null) { - fragmentManager.beginTransaction().replace(R.id.contentFrame, MainSettingsFragment()).commit() + fragmentManager.beginTransaction().replace(R.id.contentFrame, MainSettingsFragment()) + .commit() } } @@ -51,12 +50,10 @@ class SettingsActivity : AbsBaseActivity() { android.R.anim.slide_in_left, android.R.anim.slide_out_right ) - fragmentTransaction.replace(R.id.contentFrame, fragment, fragment.tag) fragmentTransaction.addToBackStack(null) fragmentTransaction.commit() - TransitionManager.beginDelayedTransition(appBarLayout) setTitle(titleName) } diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt b/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt index 944ccfbe..ae633470 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt @@ -33,12 +33,7 @@ import code.name.monkey.retromusic.glide.SongGlideRequest import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.util.Share import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.activity_share_instagram.image -import kotlinx.android.synthetic.main.activity_share_instagram.mainContent -import kotlinx.android.synthetic.main.activity_share_instagram.shareButton -import kotlinx.android.synthetic.main.activity_share_instagram.shareText -import kotlinx.android.synthetic.main.activity_share_instagram.shareTitle -import kotlinx.android.synthetic.main.activity_share_instagram.toolbar +import kotlinx.android.synthetic.main.activity_share_instagram.* /** * Created by hemanths on 2020-02-02. @@ -107,7 +102,12 @@ class ShareInstagramStory : AbsBaseActivity() { private fun setColors(colorLight: Boolean, color: Int) { setLightStatusbar(colorLight) - toolbar.setTitleTextColor(MaterialValueHelper.getPrimaryTextColor(this@ShareInstagramStory, colorLight)) + toolbar.setTitleTextColor( + MaterialValueHelper.getPrimaryTextColor( + this@ShareInstagramStory, + colorLight + ) + ) toolbar.navigationIcon?.setTintList( ColorStateList.valueOf( MaterialValueHelper.getPrimaryTextColor( @@ -117,6 +117,9 @@ class ShareInstagramStory : AbsBaseActivity() { ) ) mainContent.background = - GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, intArrayOf(color, Color.BLACK)) + GradientDrawable( + GradientDrawable.Orientation.TOP_BOTTOM, + intArrayOf(color, Color.BLACK) + ) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewActivity.java index dea4e151..631db15c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewActivity.java +++ b/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewActivity.java @@ -7,10 +7,19 @@ import android.content.pm.PackageManager; import android.graphics.Color; import android.os.Bundle; import android.webkit.WebView; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.Toolbar; import androidx.core.widget.NestedScrollView; + +import com.google.android.material.appbar.AppBarLayout; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + import code.name.monkey.appthemehelper.ThemeStore; import code.name.monkey.appthemehelper.util.ATHUtil; import code.name.monkey.appthemehelper.util.ColorUtil; @@ -18,11 +27,6 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper; import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.activities.base.AbsBaseActivity; import code.name.monkey.retromusic.util.PreferenceUtil; -import com.google.android.material.appbar.AppBarLayout; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; public class WhatsNewActivity extends AbsBaseActivity { @@ -32,6 +36,21 @@ public class WhatsNewActivity extends AbsBaseActivity { WebView webView; + private static String colorToCSS(int color) { + return String.format("rgb(%d, %d, %d)", Color.red(color), Color.green(color), + Color.blue(color)); // on API 29, WebView doesn't load with hex colors + } + + private static void setChangelogRead(@NonNull Context context) { + try { + PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + int currentVersion = pInfo.versionCode; + PreferenceUtil.getInstance(context).setLastChangeLogVersion(currentVersion); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + } + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { setDrawUnderStatusBar(); @@ -80,19 +99,4 @@ public class WhatsNewActivity extends AbsBaseActivity { } setChangelogRead(this); } - - private static String colorToCSS(int color) { - return String.format("rgb(%d, %d, %d)", Color.red(color), Color.green(color), - Color.blue(color)); // on API 29, WebView doesn't load with hex colors - } - - private static void setChangelogRead(@NonNull Context context) { - try { - PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - int currentVersion = pInfo.versionCode; - PreferenceUtil.getInstance(context).setLastChangeLogVersion(currentVersion); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt index a5c87309..c545b338 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt @@ -1,26 +1,15 @@ package code.name.monkey.retromusic.activities.base import android.Manifest -import android.content.BroadcastReceiver -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.content.ServiceConnection +import android.content.* import android.os.Bundle import android.os.IBinder import code.name.monkey.retromusic.R import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.interfaces.MusicServiceEventListener -import code.name.monkey.retromusic.service.MusicService.FAVORITE_STATE_CHANGED -import code.name.monkey.retromusic.service.MusicService.MEDIA_STORE_CHANGED -import code.name.monkey.retromusic.service.MusicService.META_CHANGED -import code.name.monkey.retromusic.service.MusicService.PLAY_STATE_CHANGED -import code.name.monkey.retromusic.service.MusicService.QUEUE_CHANGED -import code.name.monkey.retromusic.service.MusicService.REPEAT_MODE_CHANGED -import code.name.monkey.retromusic.service.MusicService.SHUFFLE_MODE_CHANGED +import code.name.monkey.retromusic.service.MusicService.* import java.lang.ref.WeakReference -import java.util.ArrayList +import java.util.* abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener { diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt index 8ab5d13b..3a84f55b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt @@ -16,21 +16,7 @@ import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.fragments.MiniPlayerFragment import code.name.monkey.retromusic.fragments.NowPlayingScreen -import code.name.monkey.retromusic.fragments.NowPlayingScreen.ADAPTIVE -import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR -import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR_CARD -import code.name.monkey.retromusic.fragments.NowPlayingScreen.CARD -import code.name.monkey.retromusic.fragments.NowPlayingScreen.CIRCLE -import code.name.monkey.retromusic.fragments.NowPlayingScreen.COLOR -import code.name.monkey.retromusic.fragments.NowPlayingScreen.FIT -import code.name.monkey.retromusic.fragments.NowPlayingScreen.FLAT -import code.name.monkey.retromusic.fragments.NowPlayingScreen.FULL -import code.name.monkey.retromusic.fragments.NowPlayingScreen.MATERIAL -import code.name.monkey.retromusic.fragments.NowPlayingScreen.NORMAL -import code.name.monkey.retromusic.fragments.NowPlayingScreen.PEAK -import code.name.monkey.retromusic.fragments.NowPlayingScreen.PLAIN -import code.name.monkey.retromusic.fragments.NowPlayingScreen.SIMPLE -import code.name.monkey.retromusic.fragments.NowPlayingScreen.TINY +import code.name.monkey.retromusic.fragments.NowPlayingScreen.* import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment import code.name.monkey.retromusic.fragments.player.adaptive.AdaptiveFragment import code.name.monkey.retromusic.fragments.player.blur.BlurPlayerFragment @@ -53,11 +39,10 @@ import code.name.monkey.retromusic.util.DensityUtil import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.views.BottomNavigationBarTinted import com.google.android.material.bottomsheet.BottomSheetBehavior -import kotlinx.android.synthetic.main.sliding_music_panel_layout.bottomNavigationView -import kotlinx.android.synthetic.main.sliding_music_panel_layout.dimBackground -import kotlinx.android.synthetic.main.sliding_music_panel_layout.slidingPanel +import kotlinx.android.synthetic.main.sliding_music_panel_layout.* -abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlayerFragment.Callbacks { +abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), + AbsPlayerFragment.Callbacks { companion object { val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName } @@ -133,8 +118,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay } protected fun wrapSlidingMusicPanel(@LayoutRes resId: Int): View { - val slidingMusicPanelLayout = layoutInflater.inflate(R.layout.sliding_music_panel_layout, null) - val contentContainer = slidingMusicPanelLayout.findViewById(R.id.mainContentFrame) + val slidingMusicPanelLayout = + layoutInflater.inflate(R.layout.sliding_music_panel_layout, null) + val contentContainer = + slidingMusicPanelLayout.findViewById(R.id.mainContentFrame) layoutInflater.inflate(resId, contentContainer) return slidingMusicPanelLayout } @@ -183,7 +170,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay } private fun setupSlidingUpPanel() { - slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object : + ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this) if (currentNowPlayingScreen != PEAK) { @@ -210,7 +198,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay private fun hideBottomBar(hide: Boolean) { val heightOfBar = resources.getDimensionPixelSize(R.dimen.mini_player_height) - val heightOfBarWithTabs = resources.getDimensionPixelSize(R.dimen.mini_player_height_expanded) + val heightOfBarWithTabs = + resources.getDimensionPixelSize(R.dimen.mini_player_height_expanded) if (hide) { bottomSheetBehavior.isHideable = true @@ -258,15 +247,18 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay .commit() supportFragmentManager.executePendingTransactions() - playerFragment = supportFragmentManager.findFragmentById(R.id.playerFragmentContainer) as AbsPlayerFragment - miniPlayerFragment = supportFragmentManager.findFragmentById(R.id.miniPlayerFragment) as MiniPlayerFragment + playerFragment = + supportFragmentManager.findFragmentById(R.id.playerFragmentContainer) as AbsPlayerFragment + miniPlayerFragment = + supportFragmentManager.findFragmentById(R.id.miniPlayerFragment) as MiniPlayerFragment miniPlayerFragment?.view?.setOnClickListener { expandPanel() } } override fun onServiceConnected() { super.onServiceConnected() if (MusicPlayerRemote.playingQueue.isNotEmpty()) { - slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object : + ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this) hideBottomBar(false) @@ -303,7 +295,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay if (PreferenceUtil.getInstance(this).adaptiveColor && (currentNowPlayingScreen == NORMAL || currentNowPlayingScreen == FLAT)) { super.setLightNavigationBar(true) super.setLightStatusbar(isColorLight) - } else if (currentNowPlayingScreen == FULL || currentNowPlayingScreen == CARD || currentNowPlayingScreen == FIT || currentNowPlayingScreen == BLUR || currentNowPlayingScreen == BLUR_CARD) { + } else if (currentNowPlayingScreen == FULL || currentNowPlayingScreen == CARD || currentNowPlayingScreen == BLUR || currentNowPlayingScreen == BLUR_CARD) { super.setLightStatusbar(false) super.setLightNavigationBar(true) super.setNavigationbarColor(Color.BLACK) @@ -311,6 +303,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay super.setNavigationbarColor(paletteColor) super.setLightNavigationBar(isColorLight) super.setLightStatusbar(isColorLight) + } else if (currentNowPlayingScreen == FIT) { + super.setLightStatusbar(false) } else { super.setLightStatusbar( ColorUtil.isColorLight( diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt index 6ea53f26..74bf61c5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt @@ -69,7 +69,10 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable { ContextCompat.getDrawable(this, R.drawable.round_window) else ContextCompat.getDrawable(this, R.drawable.square_window) background = - TintHelper.createTintedDrawable(background, ATHUtil.resolveColor(this, android.R.attr.windowBackground)) + TintHelper.createTintedDrawable( + background, + ATHUtil.resolveColor(this, android.R.attr.windowBackground) + ) window.setBackgroundDrawable(background) } @@ -92,7 +95,11 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable { if (statusBar != null) { when { VersionUtils.hasMarshmallow() -> statusBar.setBackgroundColor(color) - VersionUtils.hasLollipop() -> statusBar.setBackgroundColor(ColorUtil.darkenColor(color)) + VersionUtils.hasLollipop() -> statusBar.setBackgroundColor( + ColorUtil.darkenColor( + color + ) + ) else -> statusBar.setBackgroundColor(color) } } else { diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt index 44f8af2b..4ee68b9b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt @@ -32,19 +32,9 @@ import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.callbacks.onCancel import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.textfield.TextInputLayout -import kotlinx.android.synthetic.main.activity_bug_report.sendFab -import kotlinx.android.synthetic.main.activity_bug_report.toolbar -import kotlinx.android.synthetic.main.bug_report_card_device_info.airTextDeviceInfo -import kotlinx.android.synthetic.main.bug_report_card_report.inputDescription -import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutDescription -import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutPassword -import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutTitle -import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutUsername -import kotlinx.android.synthetic.main.bug_report_card_report.inputPassword -import kotlinx.android.synthetic.main.bug_report_card_report.inputTitle -import kotlinx.android.synthetic.main.bug_report_card_report.inputUsername -import kotlinx.android.synthetic.main.bug_report_card_report.optionAnonymous -import kotlinx.android.synthetic.main.bug_report_card_report.optionUseAccount +import kotlinx.android.synthetic.main.activity_bug_report.* +import kotlinx.android.synthetic.main.bug_report_card_device_info.* +import kotlinx.android.synthetic.main.bug_report_card_report.* import org.eclipse.egit.github.core.Issue import org.eclipse.egit.github.core.client.GitHubClient import org.eclipse.egit.github.core.client.RequestException diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.java b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.java index 94879474..ff67d14a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.java +++ b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.java @@ -5,10 +5,13 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; + import androidx.annotation.IntRange; -import code.name.monkey.retromusic.util.PreferenceUtil; + import java.util.Arrays; +import code.name.monkey.retromusic.util.PreferenceUtil; + public class DeviceInfo { @SuppressLint("NewApi") diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java index ef7ce78d..a5f2d908 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java +++ b/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java @@ -16,11 +16,14 @@ package code.name.monkey.retromusic.activities.saf; import android.os.Build; import android.os.Bundle; + import androidx.annotation.Nullable; -import code.name.monkey.retromusic.R; + import com.heinrichreimersoftware.materialintro.app.IntroActivity; import com.heinrichreimersoftware.materialintro.slide.SimpleSlide; +import code.name.monkey.retromusic.R; + /** * Created by hemanths on 2019-07-31. */ diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt index c26551d5..ed170e63 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt @@ -30,13 +30,12 @@ import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.bottomsheets.BottomSheet import com.afollestad.materialdialogs.list.listItems import com.google.android.material.button.MaterialButton -import kotlinx.android.synthetic.main.activity_album_tag_editor.editorImage -import kotlinx.android.synthetic.main.activity_album_tag_editor.imageContainer +import kotlinx.android.synthetic.main.activity_album_tag_editor.* import org.jaudiotagger.audio.AudioFile import org.jaudiotagger.audio.AudioFileIO import org.jaudiotagger.tag.FieldKey import java.io.File -import java.util.Collections +import java.util.* abstract class AbsTagEditorActivity : AbsBaseActivity() { diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt index b4c5da25..6dabc933 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt @@ -27,19 +27,9 @@ import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.request.animation.GlideAnimation import com.bumptech.glide.request.target.SimpleTarget -import kotlinx.android.synthetic.main.activity_album_tag_editor.albumArtistContainer -import kotlinx.android.synthetic.main.activity_album_tag_editor.albumArtistText -import kotlinx.android.synthetic.main.activity_album_tag_editor.albumText -import kotlinx.android.synthetic.main.activity_album_tag_editor.albumTitleContainer -import kotlinx.android.synthetic.main.activity_album_tag_editor.genreContainer -import kotlinx.android.synthetic.main.activity_album_tag_editor.genreTitle -import kotlinx.android.synthetic.main.activity_album_tag_editor.imageContainer -import kotlinx.android.synthetic.main.activity_album_tag_editor.toolbar -import kotlinx.android.synthetic.main.activity_album_tag_editor.yearContainer -import kotlinx.android.synthetic.main.activity_album_tag_editor.yearTitle +import kotlinx.android.synthetic.main.activity_album_tag_editor.* import org.jaudiotagger.tag.FieldKey -import java.util.ArrayList -import java.util.EnumMap +import java.util.* class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher { override val contentViewLayout: Int @@ -71,7 +61,10 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher { albumArtBitmap, getColor( resource?.palette, - ATHUtil.resolveColor(this@AlbumTagEditorActivity, R.attr.defaultFooterColor) + ATHUtil.resolveColor( + this@AlbumTagEditorActivity, + R.attr.defaultFooterColor + ) ) ) deleteAlbumArt = false diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt index 887b7770..d99bb70c 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt @@ -9,28 +9,9 @@ import code.name.monkey.appthemehelper.util.MaterialUtil import code.name.monkey.retromusic.R import code.name.monkey.retromusic.extensions.appHandleColor import code.name.monkey.retromusic.loaders.SongLoader -import kotlinx.android.synthetic.main.activity_song_tag_editor.albumArtistContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.albumArtistText -import kotlinx.android.synthetic.main.activity_song_tag_editor.albumText -import kotlinx.android.synthetic.main.activity_song_tag_editor.albumTextContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.artistContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.artistText -import kotlinx.android.synthetic.main.activity_song_tag_editor.composerContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.genreContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.genreText -import kotlinx.android.synthetic.main.activity_song_tag_editor.lyricsContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.lyricsText -import kotlinx.android.synthetic.main.activity_song_tag_editor.songComposerText -import kotlinx.android.synthetic.main.activity_song_tag_editor.songText -import kotlinx.android.synthetic.main.activity_song_tag_editor.songTextContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.toolbar -import kotlinx.android.synthetic.main.activity_song_tag_editor.trackNumberContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.trackNumberText -import kotlinx.android.synthetic.main.activity_song_tag_editor.yearContainer -import kotlinx.android.synthetic.main.activity_song_tag_editor.yearText +import kotlinx.android.synthetic.main.activity_song_tag_editor.* import org.jaudiotagger.tag.FieldKey -import java.util.ArrayList -import java.util.EnumMap +import java.util.* class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher { diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/WriteTagsAsyncTask.java b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/WriteTagsAsyncTask.java index 4873959f..29970c38 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/WriteTagsAsyncTask.java +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/WriteTagsAsyncTask.java @@ -7,21 +7,12 @@ import android.graphics.Bitmap; import android.media.MediaScannerConnection; import android.net.Uri; import android.os.Build; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import code.name.monkey.retromusic.R; -import code.name.monkey.retromusic.misc.DialogAsyncTask; -import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener; -import code.name.monkey.retromusic.util.MusicUtil; -import code.name.monkey.retromusic.util.SAFUtil; + import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; + import org.jaudiotagger.audio.AudioFile; import org.jaudiotagger.audio.AudioFileIO; import org.jaudiotagger.tag.FieldKey; @@ -29,28 +20,23 @@ import org.jaudiotagger.tag.Tag; import org.jaudiotagger.tag.images.Artwork; import org.jaudiotagger.tag.images.ArtworkFactory; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import code.name.monkey.retromusic.R; +import code.name.monkey.retromusic.misc.DialogAsyncTask; +import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener; +import code.name.monkey.retromusic.util.MusicUtil; +import code.name.monkey.retromusic.util.SAFUtil; + public class WriteTagsAsyncTask extends DialogAsyncTask { - public static class LoadingInfo { - - @Nullable - final Map fieldKeyValueMap; - - final Collection filePaths; - - @Nullable - private AbsTagEditorActivity.ArtworkInfo artworkInfo; - - public LoadingInfo(Collection filePaths, - @Nullable Map fieldKeyValueMap, - @Nullable AbsTagEditorActivity.ArtworkInfo artworkInfo) { - this.filePaths = filePaths; - this.fieldKeyValueMap = fieldKeyValueMap; - this.artworkInfo = artworkInfo; - } - } - private WeakReference activity; public WriteTagsAsyncTask(@NonNull Activity activity) { @@ -184,4 +170,23 @@ public class WriteTagsAsyncTask extends new UpdateToastMediaScannerCompletionListener(activity, toBeScanned)); } } + + public static class LoadingInfo { + + @Nullable + final Map fieldKeyValueMap; + + final Collection filePaths; + + @Nullable + private AbsTagEditorActivity.ArtworkInfo artworkInfo; + + public LoadingInfo(Collection filePaths, + @Nullable Map fieldKeyValueMap, + @Nullable AbsTagEditorActivity.ArtworkInfo artworkInfo) { + this.filePaths = filePaths; + this.fieldKeyValueMap = fieldKeyValueMap; + this.artworkInfo = artworkInfo; + } + } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.java b/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.java index b502d172..426eafb1 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.java +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.java @@ -39,26 +39,7 @@ import code.name.monkey.retromusic.util.SwipeAndDragHelper; public class CategoryInfoAdapter extends RecyclerView.Adapter implements SwipeAndDragHelper.ActionCompletionContract { - static class ViewHolder extends RecyclerView.ViewHolder { - - MaterialCheckBox checkBox; - - View dragView; - - TextView title; - - ViewHolder(View view) { - super(view); - checkBox = view.findViewById(R.id.checkbox); - checkBox.setButtonTintList( - ColorStateList.valueOf(ThemeStore.Companion.accentColor(checkBox.getContext()))); - title = view.findViewById(R.id.title); - dragView = view.findViewById(R.id.drag_view); - } - } - private List categoryInfos; - private ItemTouchHelper touchHelper; public CategoryInfoAdapter(@NonNull List categoryInfos) { @@ -139,4 +120,22 @@ public class CategoryInfoAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter implements MaterialCab.Callback { - private MaterialCab cab; - @Nullable private final CabHolder cabHolder; - - private ArrayList checked; - private final Context context; - + private MaterialCab cab; + private ArrayList checked; private int menuRes; public AbsMultiSelectAdapter(@NonNull Context context, @Nullable CabHolder cabHolder, @MenuRes int menuRes) { diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java index 014d7ea1..01971b12 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java @@ -20,13 +20,16 @@ import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; -import code.name.monkey.retromusic.R; + import com.google.android.material.card.MaterialCardView; import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableSwipeableItemViewHolder; +import code.name.monkey.retromusic.R; + public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHolder implements View.OnLongClickListener, View.OnClickListener { diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt index c13f116c..8c6a6c80 100755 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt @@ -30,7 +30,7 @@ import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.NavigationUtil -import java.util.ArrayList +import java.util.* class PlaylistAdapter( private val activity: AppCompatActivity, @@ -172,7 +172,8 @@ class PlaylistAdapter( init { image?.apply { - val iconPadding = activity.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding) + val iconPadding = + activity.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding) setPadding(iconPadding, iconPadding, iconPadding, iconPadding) } diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt index 5d216fff..89d3e511 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt @@ -19,7 +19,8 @@ abstract class AbsOffsetSongAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongAdapter.ViewHolder { if (viewType == OFFSET_ITEM) { - val view = LayoutInflater.from(activity).inflate(R.layout.item_list_quick_actions, parent, false) + val view = LayoutInflater.from(activity) + .inflate(R.layout.item_list_quick_actions, parent, false) return createViewHolder(view) } return super.onCreateViewHolder(parent, viewType) diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt index a8d764b9..74a2f7eb 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt @@ -91,7 +91,8 @@ class OrderablePlaylistSongAdapter( fun onMoveItem(fromPosition: Int, toPosition: Int) } - inner class ViewHolder(itemView: View) : PlaylistSongAdapter.ViewHolder(itemView), DraggableItemViewHolder { + inner class ViewHolder(itemView: View) : PlaylistSongAdapter.ViewHolder(itemView), + DraggableItemViewHolder { @DraggableItemStateFlags private var mDragStateFlags: Int = 0 diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt index 1a722bd3..04a998e6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt @@ -23,7 +23,7 @@ import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultAct import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionRemoveItem import com.h6ah4i.android.widget.advrecyclerview.swipeable.annotation.SwipeableItemResults import me.zhanghai.android.fastscroll.PopupTextProvider -import java.util.ArrayList +import java.util.* class PlayingQueueAdapter( activity: AppCompatActivity, @@ -32,7 +32,8 @@ class PlayingQueueAdapter( itemLayoutRes: Int ) : SongAdapter( activity, dataSet, itemLayoutRes, null -), DraggableItemAdapter, SwipeableItemAdapter, +), DraggableItemAdapter, + SwipeableItemAdapter, PopupTextProvider { private var color = -1 @@ -107,7 +108,11 @@ class PlayingQueueAdapter( } override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean { - return ViewUtil.hitTest(holder.imageText!!, x, y) || ViewUtil.hitTest(holder.dragView!!, x, y) + return ViewUtil.hitTest(holder.imageText!!, x, y) || ViewUtil.hitTest( + holder.dragView!!, + x, + y + ) } override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange? { diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutIconGenerator.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutIconGenerator.kt index 70565d5a..15e1b302 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutIconGenerator.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutIconGenerator.kt @@ -15,69 +15,73 @@ package code.name.monkey.retromusic.appshortcuts import android.content.Context -import android.graphics.* -import android.graphics.drawable.* +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.drawable.Drawable +import android.graphics.drawable.Icon +import android.graphics.drawable.LayerDrawable import android.os.Build import android.util.TypedValue import androidx.annotation.RequiresApi import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.retromusic.R -import code.name.monkey.retromusic.util.* +import code.name.monkey.retromusic.util.PreferenceUtil +import code.name.monkey.retromusic.util.RetroUtil @RequiresApi(Build.VERSION_CODES.N_MR1) object AppShortcutIconGenerator { - fun generateThemedIcon(context: Context, iconId: Int): Icon { - return if (PreferenceUtil.getInstance(context).coloredAppShortcuts()) { - generateUserThemedIcon(context, iconId) - } else { - generateDefaultThemedIcon(context, iconId) - } - } + fun generateThemedIcon(context: Context, iconId: Int): Icon { + return if (PreferenceUtil.getInstance(context).coloredAppShortcuts()) { + generateUserThemedIcon(context, iconId) + } else { + generateDefaultThemedIcon(context, iconId) + } + } - private fun generateDefaultThemedIcon(context: Context, iconId: Int): Icon { - // Return an Icon of iconId with default colors - return generateThemedIcon( - context, - iconId, - context.getColor(R.color.app_shortcut_default_foreground), - context.getColor(R.color.app_shortcut_default_background) - ) - } + private fun generateDefaultThemedIcon(context: Context, iconId: Int): Icon { + // Return an Icon of iconId with default colors + return generateThemedIcon( + context, + iconId, + context.getColor(R.color.app_shortcut_default_foreground), + context.getColor(R.color.app_shortcut_default_background) + ) + } - private fun generateUserThemedIcon(context: Context, iconId: Int): Icon { - // Get background color from context's theme - val typedColorBackground = TypedValue() - context.theme.resolveAttribute(android.R.attr.colorBackground, typedColorBackground, true) + private fun generateUserThemedIcon(context: Context, iconId: Int): Icon { + // Get background color from context's theme + val typedColorBackground = TypedValue() + context.theme.resolveAttribute(android.R.attr.colorBackground, typedColorBackground, true) - // Return an Icon of iconId with those colors - return generateThemedIcon( - context, iconId, ThemeStore.accentColor(context), typedColorBackground.data - ) - } + // Return an Icon of iconId with those colors + return generateThemedIcon( + context, iconId, ThemeStore.accentColor(context), typedColorBackground.data + ) + } - private fun generateThemedIcon( - context: Context, iconId: Int, foregroundColor: Int, backgroundColor: Int - ): Icon { - // Get and tint foreground and background drawables - val vectorDrawable = RetroUtil.getTintedVectorDrawable(context, iconId, foregroundColor) - val backgroundDrawable = RetroUtil.getTintedVectorDrawable( - context, R.drawable.ic_app_shortcut_background, backgroundColor - ) + private fun generateThemedIcon( + context: Context, iconId: Int, foregroundColor: Int, backgroundColor: Int + ): Icon { + // Get and tint foreground and background drawables + val vectorDrawable = RetroUtil.getTintedVectorDrawable(context, iconId, foregroundColor) + val backgroundDrawable = RetroUtil.getTintedVectorDrawable( + context, R.drawable.ic_app_shortcut_background, backgroundColor + ) - // Squash the two drawables together - val layerDrawable = LayerDrawable(arrayOf(backgroundDrawable, vectorDrawable)) + // Squash the two drawables together + val layerDrawable = LayerDrawable(arrayOf(backgroundDrawable, vectorDrawable)) - // Return as an Icon - return Icon.createWithBitmap(drawableToBitmap(layerDrawable)) - } + // Return as an Icon + return Icon.createWithBitmap(drawableToBitmap(layerDrawable)) + } - private fun drawableToBitmap(drawable: Drawable): Bitmap { - val bitmap = Bitmap.createBitmap( - drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888 - ) - val canvas = Canvas(bitmap) - drawable.setBounds(0, 0, canvas.width, canvas.height) - drawable.draw(canvas) - return bitmap - } + private fun drawableToBitmap(drawable: Drawable): Bitmap { + val bitmap = Bitmap.createBitmap( + drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888 + ) + val canvas = Canvas(bitmap) + drawable.setBounds(0, 0, canvas.width, canvas.height) + drawable.draw(canvas) + return bitmap + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutLauncherActivity.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutLauncherActivity.kt index 0426ff65..1bf1e90c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutLauncherActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/AppShortcutLauncherActivity.kt @@ -18,71 +18,76 @@ import android.app.Activity import android.content.Intent import android.os.Bundle import code.name.monkey.retromusic.activities.SearchActivity -import code.name.monkey.retromusic.appshortcuts.shortcuttype.* +import code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType +import code.name.monkey.retromusic.appshortcuts.shortcuttype.SearchShortCutType +import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType +import code.name.monkey.retromusic.appshortcuts.shortcuttype.TopTracksShortcutType import code.name.monkey.retromusic.model.Playlist -import code.name.monkey.retromusic.model.smartplaylist.* +import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist +import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist +import code.name.monkey.retromusic.model.smartplaylist.ShuffleAllPlaylist import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService.* class AppShortcutLauncherActivity : Activity() { - public override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) - var shortcutType = SHORTCUT_TYPE_NONE + var shortcutType = SHORTCUT_TYPE_NONE - // Set shortcutType from the intent extras - val extras = intent.extras - if (extras != null) { - shortcutType = extras.getInt(KEY_SHORTCUT_TYPE, SHORTCUT_TYPE_NONE) - } + // Set shortcutType from the intent extras + val extras = intent.extras + if (extras != null) { + shortcutType = extras.getInt(KEY_SHORTCUT_TYPE, SHORTCUT_TYPE_NONE) + } - when (shortcutType) { - SHORTCUT_TYPE_SHUFFLE_ALL -> { - startServiceWithPlaylist( - MusicService.SHUFFLE_MODE_SHUFFLE, ShuffleAllPlaylist(applicationContext) - ) - DynamicShortcutManager.reportShortcutUsed(this, ShuffleAllShortcutType.id) - } - SHORTCUT_TYPE_TOP_TRACKS -> { - startServiceWithPlaylist( - MusicService.SHUFFLE_MODE_NONE, MyTopTracksPlaylist(applicationContext) - ) - DynamicShortcutManager.reportShortcutUsed(this, TopTracksShortcutType.id) - } - SHORTCUT_TYPE_LAST_ADDED -> { - startServiceWithPlaylist( - MusicService.SHUFFLE_MODE_NONE, LastAddedPlaylist(applicationContext) - ) - DynamicShortcutManager.reportShortcutUsed(this, LastAddedShortcutType.id) - } - SHORTCUT_TYPE_SEARCH -> { - startActivity(Intent(this, SearchActivity::class.java)) - DynamicShortcutManager.reportShortcutUsed(this, SearchShortCutType.id) - } - } - finish() - } + when (shortcutType) { + SHORTCUT_TYPE_SHUFFLE_ALL -> { + startServiceWithPlaylist( + MusicService.SHUFFLE_MODE_SHUFFLE, ShuffleAllPlaylist(applicationContext) + ) + DynamicShortcutManager.reportShortcutUsed(this, ShuffleAllShortcutType.id) + } + SHORTCUT_TYPE_TOP_TRACKS -> { + startServiceWithPlaylist( + MusicService.SHUFFLE_MODE_NONE, MyTopTracksPlaylist(applicationContext) + ) + DynamicShortcutManager.reportShortcutUsed(this, TopTracksShortcutType.id) + } + SHORTCUT_TYPE_LAST_ADDED -> { + startServiceWithPlaylist( + MusicService.SHUFFLE_MODE_NONE, LastAddedPlaylist(applicationContext) + ) + DynamicShortcutManager.reportShortcutUsed(this, LastAddedShortcutType.id) + } + SHORTCUT_TYPE_SEARCH -> { + startActivity(Intent(this, SearchActivity::class.java)) + DynamicShortcutManager.reportShortcutUsed(this, SearchShortCutType.id) + } + } + finish() + } - private fun startServiceWithPlaylist(shuffleMode: Int, playlist: Playlist) { - val intent = Intent(this, MusicService::class.java) - intent.action = ACTION_PLAY_PLAYLIST + private fun startServiceWithPlaylist(shuffleMode: Int, playlist: Playlist) { + val intent = Intent(this, MusicService::class.java) + intent.action = ACTION_PLAY_PLAYLIST - val bundle = Bundle() - bundle.putParcelable(INTENT_EXTRA_PLAYLIST, playlist) - bundle.putInt(INTENT_EXTRA_SHUFFLE_MODE, shuffleMode) + val bundle = Bundle() + bundle.putParcelable(INTENT_EXTRA_PLAYLIST, playlist) + bundle.putInt(INTENT_EXTRA_SHUFFLE_MODE, shuffleMode) - intent.putExtras(bundle) + intent.putExtras(bundle) - startService(intent) - } + startService(intent) + } - companion object { - const val KEY_SHORTCUT_TYPE = "code.name.monkey.retromusic.appshortcuts.ShortcutType" - const val SHORTCUT_TYPE_SHUFFLE_ALL = 0 - const val SHORTCUT_TYPE_TOP_TRACKS = 1 - const val SHORTCUT_TYPE_LAST_ADDED = 2 - const val SHORTCUT_TYPE_SEARCH = 3 - const val SHORTCUT_TYPE_NONE = 4 - } + companion object { + const val KEY_SHORTCUT_TYPE = "code.name.monkey.retromusic.appshortcuts.ShortcutType" + const val SHORTCUT_TYPE_SHUFFLE_ALL = 0 + const val SHORTCUT_TYPE_TOP_TRACKS = 1 + const val SHORTCUT_TYPE_LAST_ADDED = 2 + const val SHORTCUT_TYPE_SEARCH = 3 + const val SHORTCUT_TYPE_NONE = 4 + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/DynamicShortcutManager.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/DynamicShortcutManager.kt index 790afe57..c77df6b5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/DynamicShortcutManager.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/DynamicShortcutManager.kt @@ -15,52 +15,58 @@ package code.name.monkey.retromusic.appshortcuts import android.annotation.TargetApi -import android.content.* -import android.content.pm.* +import android.content.Context +import android.content.Intent +import android.content.pm.ShortcutInfo +import android.content.pm.ShortcutManager import android.graphics.drawable.Icon import android.os.Build -import code.name.monkey.retromusic.appshortcuts.shortcuttype.* +import code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType +import code.name.monkey.retromusic.appshortcuts.shortcuttype.SearchShortCutType +import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType +import code.name.monkey.retromusic.appshortcuts.shortcuttype.TopTracksShortcutType import java.util.* @TargetApi(Build.VERSION_CODES.N_MR1) class DynamicShortcutManager(private val context: Context) { - private val shortcutManager: ShortcutManager = this.context.getSystemService(ShortcutManager::class.java) + private val shortcutManager: ShortcutManager = + this.context.getSystemService(ShortcutManager::class.java) - private val defaultShortcuts: List - get() = Arrays.asList( - SearchShortCutType(context).shortcutInfo, - ShuffleAllShortcutType(context).shortcutInfo, - TopTracksShortcutType(context).shortcutInfo, - LastAddedShortcutType(context).shortcutInfo + private val defaultShortcuts: List + get() = Arrays.asList( + SearchShortCutType(context).shortcutInfo, + ShuffleAllShortcutType(context).shortcutInfo, + TopTracksShortcutType(context).shortcutInfo, + LastAddedShortcutType(context).shortcutInfo - ) + ) - fun initDynamicShortcuts() { - //if (shortcutManager.dynamicShortcuts.size == 0) { - shortcutManager.dynamicShortcuts = defaultShortcuts - //} - } + fun initDynamicShortcuts() { + //if (shortcutManager.dynamicShortcuts.size == 0) { + shortcutManager.dynamicShortcuts = defaultShortcuts + //} + } - fun updateDynamicShortcuts() { - shortcutManager.updateShortcuts(defaultShortcuts) - } + fun updateDynamicShortcuts() { + shortcutManager.updateShortcuts(defaultShortcuts) + } - companion object { + companion object { - fun createShortcut( - context: Context, - id: String, - shortLabel: String, - longLabel: String, - icon: Icon, - intent: Intent - ): ShortcutInfo { - return ShortcutInfo.Builder(context, id).setShortLabel(shortLabel) - .setLongLabel(longLabel).setIcon(icon).setIntent(intent).build() - } + fun createShortcut( + context: Context, + id: String, + shortLabel: String, + longLabel: String, + icon: Icon, + intent: Intent + ): ShortcutInfo { + return ShortcutInfo.Builder(context, id).setShortLabel(shortLabel) + .setLongLabel(longLabel).setIcon(icon).setIntent(intent).build() + } - fun reportShortcutUsed(context: Context, shortcutId: String) { - context.getSystemService(ShortcutManager::class.java).reportShortcutUsed(shortcutId) - } - } + fun reportShortcutUsed(context: Context, shortcutId: String) { + context.getSystemService(ShortcutManager::class.java).reportShortcutUsed(shortcutId) + } + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/BaseShortcutType.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/BaseShortcutType.kt index 5ca1284d..c2b376de 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/BaseShortcutType.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/BaseShortcutType.kt @@ -15,34 +15,36 @@ package code.name.monkey.retromusic.appshortcuts.shortcuttype import android.annotation.TargetApi -import android.content.* +import android.content.Context +import android.content.Intent import android.content.pm.ShortcutInfo -import android.os.* +import android.os.Build +import android.os.Bundle import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity @TargetApi(Build.VERSION_CODES.N_MR1) abstract class BaseShortcutType(internal var context: Context) { - internal abstract val shortcutInfo: ShortcutInfo + internal abstract val shortcutInfo: ShortcutInfo - /** - * Creates an Intent that will launch MainActivtiy and immediately play {@param songs} in either shuffle or normal mode - * - * @param shortcutType Describes the type of shortcut to create (ShuffleAll, TopTracks, custom playlist, etc.) - * @return - */ - internal fun getPlaySongsIntent(shortcutType: Int): Intent { - val intent = Intent(context, AppShortcutLauncherActivity::class.java) - intent.action = Intent.ACTION_VIEW - val b = Bundle() - b.putInt(AppShortcutLauncherActivity.KEY_SHORTCUT_TYPE, shortcutType) - intent.putExtras(b) - return intent - } + /** + * Creates an Intent that will launch MainActivtiy and immediately play {@param songs} in either shuffle or normal mode + * + * @param shortcutType Describes the type of shortcut to create (ShuffleAll, TopTracks, custom playlist, etc.) + * @return + */ + internal fun getPlaySongsIntent(shortcutType: Int): Intent { + val intent = Intent(context, AppShortcutLauncherActivity::class.java) + intent.action = Intent.ACTION_VIEW + val b = Bundle() + b.putInt(AppShortcutLauncherActivity.KEY_SHORTCUT_TYPE, shortcutType) + intent.putExtras(b) + return intent + } - companion object { - internal const val ID_PREFIX = "code.name.monkey.retromusic.appshortcuts.id." - val id: String - get() = ID_PREFIX + "invalid" - } + companion object { + internal const val ID_PREFIX = "code.name.monkey.retromusic.appshortcuts.id." + val id: String + get() = ID_PREFIX + "invalid" + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/LastAddedShortcutType.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/LastAddedShortcutType.kt index df92969b..b590a943 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/LastAddedShortcutType.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/LastAddedShortcutType.kt @@ -19,27 +19,28 @@ import android.content.Context import android.content.pm.ShortcutInfo import android.os.Build import code.name.monkey.retromusic.R -import code.name.monkey.retromusic.appshortcuts.* +import code.name.monkey.retromusic.appshortcuts.AppShortcutIconGenerator +import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity @TargetApi(Build.VERSION_CODES.N_MR1) class LastAddedShortcutType(context: Context) : BaseShortcutType(context) { - override val shortcutInfo: ShortcutInfo - get() = ShortcutInfo.Builder( - context, - id - ).setShortLabel(context.getString(R.string.app_shortcut_last_added_short)).setLongLabel( - context.getString(R.string.app_shortcut_last_added_long) - ).setIcon( - AppShortcutIconGenerator.generateThemedIcon( - context, - R.drawable.ic_app_shortcut_last_added - ) - ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_LAST_ADDED)).build() + override val shortcutInfo: ShortcutInfo + get() = ShortcutInfo.Builder( + context, + id + ).setShortLabel(context.getString(R.string.app_shortcut_last_added_short)).setLongLabel( + context.getString(R.string.app_shortcut_last_added_long) + ).setIcon( + AppShortcutIconGenerator.generateThemedIcon( + context, + R.drawable.ic_app_shortcut_last_added + ) + ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_LAST_ADDED)).build() - companion object { + companion object { - val id: String - get() = BaseShortcutType.ID_PREFIX + "last_added" - } + val id: String + get() = BaseShortcutType.ID_PREFIX + "last_added" + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/SearchShortCutType.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/SearchShortCutType.kt index ca2e7c4a..60c91883 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/SearchShortCutType.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/SearchShortCutType.kt @@ -19,24 +19,25 @@ import android.content.Context import android.content.pm.ShortcutInfo import android.os.Build import code.name.monkey.retromusic.R -import code.name.monkey.retromusic.appshortcuts.* +import code.name.monkey.retromusic.appshortcuts.AppShortcutIconGenerator +import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity @TargetApi(Build.VERSION_CODES.N_MR1) class SearchShortCutType(context: Context) : BaseShortcutType(context) { - companion object { + companion object { - val id: String - get() = BaseShortcutType.ID_PREFIX + "search" - } + val id: String + get() = BaseShortcutType.ID_PREFIX + "search" + } - override val shortcutInfo: ShortcutInfo - get() = ShortcutInfo.Builder( - context, - id - ).setShortLabel(context.getString(R.string.action_search)).setLongLabel(context.getString(R.string.search_hint)).setIcon( - AppShortcutIconGenerator.generateThemedIcon( - context, - R.drawable.ic_app_shortcut_search - ) - ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_SEARCH)).build() + override val shortcutInfo: ShortcutInfo + get() = ShortcutInfo.Builder( + context, + id + ).setShortLabel(context.getString(R.string.action_search)).setLongLabel(context.getString(R.string.search_hint)).setIcon( + AppShortcutIconGenerator.generateThemedIcon( + context, + R.drawable.ic_app_shortcut_search + ) + ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_SEARCH)).build() } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/ShuffleAllShortcutType.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/ShuffleAllShortcutType.kt index c5b7f24c..8f869d20 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/ShuffleAllShortcutType.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/ShuffleAllShortcutType.kt @@ -19,25 +19,26 @@ import android.content.Context import android.content.pm.ShortcutInfo import android.os.Build import code.name.monkey.retromusic.R -import code.name.monkey.retromusic.appshortcuts.* +import code.name.monkey.retromusic.appshortcuts.AppShortcutIconGenerator +import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity @TargetApi(Build.VERSION_CODES.N_MR1) class ShuffleAllShortcutType(context: Context) : BaseShortcutType(context) { - override val shortcutInfo: ShortcutInfo - get() = ShortcutInfo.Builder( - context, id - ).setShortLabel(context.getString(R.string.app_shortcut_shuffle_all_short)).setLongLabel( - context.getString(R.string.app_shortcut_shuffle_all_long) - ).setIcon( - AppShortcutIconGenerator.generateThemedIcon( - context, R.drawable.ic_app_shortcut_shuffle_all - ) - ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_SHUFFLE_ALL)).build() + override val shortcutInfo: ShortcutInfo + get() = ShortcutInfo.Builder( + context, id + ).setShortLabel(context.getString(R.string.app_shortcut_shuffle_all_short)).setLongLabel( + context.getString(R.string.app_shortcut_shuffle_all_long) + ).setIcon( + AppShortcutIconGenerator.generateThemedIcon( + context, R.drawable.ic_app_shortcut_shuffle_all + ) + ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_SHUFFLE_ALL)).build() - companion object { + companion object { - val id: String - get() = BaseShortcutType.ID_PREFIX + "shuffle_all" - } + val id: String + get() = BaseShortcutType.ID_PREFIX + "shuffle_all" + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/TopTracksShortcutType.kt b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/TopTracksShortcutType.kt index 32e53e41..ed274cdd 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/TopTracksShortcutType.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appshortcuts/shortcuttype/TopTracksShortcutType.kt @@ -19,25 +19,26 @@ import android.content.Context import android.content.pm.ShortcutInfo import android.os.Build import code.name.monkey.retromusic.R -import code.name.monkey.retromusic.appshortcuts.* +import code.name.monkey.retromusic.appshortcuts.AppShortcutIconGenerator +import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity @TargetApi(Build.VERSION_CODES.N_MR1) class TopTracksShortcutType(context: Context) : BaseShortcutType(context) { - override val shortcutInfo: ShortcutInfo - get() = ShortcutInfo.Builder( - context, id - ).setShortLabel(context.getString(R.string.app_shortcut_top_tracks_short)).setLongLabel( - context.getString(R.string.app_shortcut_top_tracks_long) - ).setIcon( - AppShortcutIconGenerator.generateThemedIcon( - context, R.drawable.ic_app_shortcut_top_tracks - ) - ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_TOP_TRACKS)).build() + override val shortcutInfo: ShortcutInfo + get() = ShortcutInfo.Builder( + context, id + ).setShortLabel(context.getString(R.string.app_shortcut_top_tracks_short)).setLongLabel( + context.getString(R.string.app_shortcut_top_tracks_long) + ).setIcon( + AppShortcutIconGenerator.generateThemedIcon( + context, R.drawable.ic_app_shortcut_top_tracks + ) + ).setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_TOP_TRACKS)).build() - companion object { + companion object { - val id: String - get() = BaseShortcutType.ID_PREFIX + "top_tracks" - } + val id: String + get() = BaseShortcutType.ID_PREFIX + "top_tracks" + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetBig.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetBig.kt index a440b0bc..22951613 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetBig.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetBig.kt @@ -45,40 +45,40 @@ class AppWidgetBig : BaseAppWidget() { */ override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) { val appWidgetView = RemoteViews( - context.packageName, code.name.monkey.retromusic.R.layout.app_widget_big + context.packageName, code.name.monkey.retromusic.R.layout.app_widget_big ) appWidgetView.setViewVisibility( - code.name.monkey.retromusic.R.id.media_titles, - View.INVISIBLE + code.name.monkey.retromusic.R.id.media_titles, + View.INVISIBLE ) appWidgetView.setImageViewResource(R.id.image, R.drawable.default_audio_art) appWidgetView.setImageViewBitmap( - R.id.button_next, BaseAppWidget.createBitmap( + R.id.button_next, BaseAppWidget.createBitmap( RetroUtil.getTintedVectorDrawable( - context, - code.name.monkey.retromusic.R.drawable.ic_skip_next_white_24dp, - MaterialValueHelper.getPrimaryTextColor(context, false) + context, + code.name.monkey.retromusic.R.drawable.ic_skip_next_white_24dp, + MaterialValueHelper.getPrimaryTextColor(context, false) )!!, 1f - ) + ) ) appWidgetView.setImageViewBitmap( - R.id.button_prev, BaseAppWidget.Companion.createBitmap( + R.id.button_prev, BaseAppWidget.Companion.createBitmap( RetroUtil.getTintedVectorDrawable( - context, - code.name.monkey.retromusic.R.drawable.ic_skip_previous_white_24dp, - MaterialValueHelper.getPrimaryTextColor(context, false) + context, + code.name.monkey.retromusic.R.drawable.ic_skip_previous_white_24dp, + MaterialValueHelper.getPrimaryTextColor(context, false) )!!, 1f - ) + ) ) appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap( + R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap( RetroUtil.getTintedVectorDrawable( - context, - code.name.monkey.retromusic.R.drawable.ic_play_arrow_white_32dp, - MaterialValueHelper.getPrimaryTextColor(context, false) + context, + code.name.monkey.retromusic.R.drawable.ic_play_arrow_white_32dp, + MaterialValueHelper.getPrimaryTextColor(context, false) )!!, 1f - ) + ) ) linkButtons(context, appWidgetView) @@ -90,7 +90,7 @@ class AppWidgetBig : BaseAppWidget() { */ override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) { val appWidgetView = RemoteViews( - service.packageName, code.name.monkey.retromusic.R.layout.app_widget_big + service.packageName, code.name.monkey.retromusic.R.layout.app_widget_big ) val isPlaying = service.isPlaying @@ -99,51 +99,52 @@ class AppWidgetBig : BaseAppWidget() { // Set the titles and artwork if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) { appWidgetView.setViewVisibility( - code.name.monkey.retromusic.R.id.media_titles, - View.INVISIBLE + code.name.monkey.retromusic.R.id.media_titles, + View.INVISIBLE ) } else { appWidgetView.setViewVisibility( - code.name.monkey.retromusic.R.id.media_titles, - View.VISIBLE + code.name.monkey.retromusic.R.id.media_titles, + View.VISIBLE ) appWidgetView.setTextViewText(code.name.monkey.retromusic.R.id.title, song.title) appWidgetView.setTextViewText( - code.name.monkey.retromusic.R.id.text, - getSongArtistAndAlbum(song) + code.name.monkey.retromusic.R.id.text, + getSongArtistAndAlbum(song) ) } // Set correct drawable for pause state - val playPauseRes = if (isPlaying) code.name.monkey.retromusic.R.drawable.ic_pause_white_24dp else code.name.monkey.retromusic.R.drawable.ic_play_arrow_white_32dp + val playPauseRes = + if (isPlaying) code.name.monkey.retromusic.R.drawable.ic_pause_white_24dp else code.name.monkey.retromusic.R.drawable.ic_play_arrow_white_32dp appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, BaseAppWidget.createBitmap( + R.id.button_toggle_play_pause, BaseAppWidget.createBitmap( RetroUtil.getTintedVectorDrawable( - service, - playPauseRes, - MaterialValueHelper.getPrimaryTextColor(service, false) + service, + playPauseRes, + MaterialValueHelper.getPrimaryTextColor(service, false) )!!, 1f - ) + ) ) // Set prev/next button drawables appWidgetView.setImageViewBitmap( - R.id.button_next, BaseAppWidget.Companion.createBitmap( + R.id.button_next, BaseAppWidget.Companion.createBitmap( RetroUtil.getTintedVectorDrawable( - service, - code.name.monkey.retromusic.R.drawable.ic_skip_next_white_24dp, - MaterialValueHelper.getPrimaryTextColor(service, false) + service, + code.name.monkey.retromusic.R.drawable.ic_skip_next_white_24dp, + MaterialValueHelper.getPrimaryTextColor(service, false) )!!, 1f - ) + ) ) appWidgetView.setImageViewBitmap( - R.id.button_prev, BaseAppWidget.Companion.createBitmap( + R.id.button_prev, BaseAppWidget.Companion.createBitmap( RetroUtil.getTintedVectorDrawable( - service, - code.name.monkey.retromusic.R.drawable.ic_skip_previous_white_24dp, - MaterialValueHelper.getPrimaryTextColor(service, false) + service, + code.name.monkey.retromusic.R.drawable.ic_skip_previous_white_24dp, + MaterialValueHelper.getPrimaryTextColor(service, false) )!!, 1f - ) + ) ) // Link actions buttons to intents @@ -158,32 +159,32 @@ class AppWidgetBig : BaseAppWidget() { Glide.clear(target) } target = SongGlideRequest.Builder.from(Glide.with(appContext), song) - .checkIgnoreMediaStore(appContext).asBitmap().build() - .into(object : SimpleTarget(widgetImageSize, widgetImageSize) { - override fun onResourceReady( - resource: Bitmap, - glideAnimation: GlideAnimation - ) { - update(resource) - } + .checkIgnoreMediaStore(appContext).asBitmap().build() + .into(object : SimpleTarget(widgetImageSize, widgetImageSize) { + override fun onResourceReady( + resource: Bitmap, + glideAnimation: GlideAnimation + ) { + update(resource) + } - override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { - super.onLoadFailed(e, errorDrawable) - update(null) - } + override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { + super.onLoadFailed(e, errorDrawable) + update(null) + } - private fun update(bitmap: Bitmap?) { - if (bitmap == null) { - appWidgetView.setImageViewResource( - R.id.image, - R.drawable.default_audio_art - ) - } else { - appWidgetView.setImageViewBitmap(R.id.image, bitmap) - } - pushUpdate(appContext, appWidgetIds, appWidgetView) + private fun update(bitmap: Bitmap?) { + if (bitmap == null) { + appWidgetView.setImageViewResource( + R.id.image, + R.drawable.default_audio_art + ) + } else { + appWidgetView.setImageViewBitmap(R.id.image, bitmap) } - }); + pushUpdate(appContext, appWidgetIds, appWidgetView) + } + }); } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetCard.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetCard.kt index c92772e5..38b73698 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetCard.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetCard.kt @@ -15,7 +15,9 @@ package code.name.monkey.retromusic.appwidgets import android.app.PendingIntent -import android.content.* +import android.content.ComponentName +import android.content.Context +import android.content.Intent import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.text.TextUtils @@ -29,231 +31,235 @@ import code.name.monkey.retromusic.glide.SongGlideRequest import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService.* -import code.name.monkey.retromusic.util.* +import code.name.monkey.retromusic.util.ImageUtil +import code.name.monkey.retromusic.util.RetroUtil import com.bumptech.glide.Glide import com.bumptech.glide.request.animation.GlideAnimation -import com.bumptech.glide.request.target.* +import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.target.Target class AppWidgetCard : BaseAppWidget() { - private var target: Target? = null // for cancellation + private var target: Target? = null // for cancellation - /** - * Initialize given widgets to default state, where we launch Music on default click and hide - * actions if service not running. - */ - override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) { - val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_card) + /** + * Initialize given widgets to default state, where we launch Music on default click and hide + * actions if service not running. + */ + override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) { + val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_card) - appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE) - appWidgetView.setImageViewResource(R.id.image, R.drawable.default_audio_art) - appWidgetView.setImageViewBitmap( - R.id.button_next, createBitmap( - RetroUtil.getTintedVectorDrawable( - context, - R.drawable.ic_skip_next_white_24dp, - MaterialValueHelper.getSecondaryTextColor( - context, true - ) - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_prev, createBitmap( - RetroUtil.getTintedVectorDrawable( - context, - R.drawable.ic_skip_previous_white_24dp, - MaterialValueHelper.getSecondaryTextColor( - context, true - ) - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, createBitmap( - RetroUtil.getTintedVectorDrawable( - context, - R.drawable.ic_play_arrow_white_32dp, - MaterialValueHelper.getSecondaryTextColor( - context, true - ) - )!!, 1f - ) - ) + appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE) + appWidgetView.setImageViewResource(R.id.image, R.drawable.default_audio_art) + appWidgetView.setImageViewBitmap( + R.id.button_next, createBitmap( + RetroUtil.getTintedVectorDrawable( + context, + R.drawable.ic_skip_next_white_24dp, + MaterialValueHelper.getSecondaryTextColor( + context, true + ) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_prev, createBitmap( + RetroUtil.getTintedVectorDrawable( + context, + R.drawable.ic_skip_previous_white_24dp, + MaterialValueHelper.getSecondaryTextColor( + context, true + ) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, createBitmap( + RetroUtil.getTintedVectorDrawable( + context, + R.drawable.ic_play_arrow_white_32dp, + MaterialValueHelper.getSecondaryTextColor( + context, true + ) + )!!, 1f + ) + ) - linkButtons(context, appWidgetView) - pushUpdate(context, appWidgetIds, appWidgetView) - } + linkButtons(context, appWidgetView) + pushUpdate(context, appWidgetIds, appWidgetView) + } - /** - * Update all active widget instances by pushing changes - */ - override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) { - val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_card) + /** + * Update all active widget instances by pushing changes + */ + override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) { + val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_card) - val isPlaying = service.isPlaying - val song = service.currentSong + val isPlaying = service.isPlaying + val song = service.currentSong - // Set the titles and artwork - if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) { - appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE) - } else { - appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE) - appWidgetView.setTextViewText(R.id.title, song.title) - appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song)) - } + // Set the titles and artwork + if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) { + appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE) + } else { + appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE) + appWidgetView.setTextViewText(R.id.title, song.title) + appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song)) + } - // Set correct drawable for pause state - val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_32dp - appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, createBitmap( - RetroUtil.getTintedVectorDrawable( - service, - playPauseRes, - MaterialValueHelper.getSecondaryTextColor(service, true) - )!!, 1f - ) - ) + // Set correct drawable for pause state + val playPauseRes = + if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_32dp + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + playPauseRes, + MaterialValueHelper.getSecondaryTextColor(service, true) + )!!, 1f + ) + ) - // Set prev/next button drawables - appWidgetView.setImageViewBitmap( - R.id.button_next, createBitmap( - RetroUtil.getTintedVectorDrawable( - service, - R.drawable.ic_skip_next_white_24dp, - MaterialValueHelper.getSecondaryTextColor(service, true) - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_prev, createBitmap( - RetroUtil.getTintedVectorDrawable( - service, - R.drawable.ic_skip_previous_white_24dp, - MaterialValueHelper.getSecondaryTextColor(service, true) - )!!, 1f - ) - ) + // Set prev/next button drawables + appWidgetView.setImageViewBitmap( + R.id.button_next, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + R.drawable.ic_skip_next_white_24dp, + MaterialValueHelper.getSecondaryTextColor(service, true) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_prev, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + R.drawable.ic_skip_previous_white_24dp, + MaterialValueHelper.getSecondaryTextColor(service, true) + )!!, 1f + ) + ) - // Link actions buttons to intents - linkButtons(service, appWidgetView) + // Link actions buttons to intents + linkButtons(service, appWidgetView) - if (imageSize == 0) { - imageSize = service.resources.getDimensionPixelSize(code.name.monkey.retromusic.R.dimen.app_widget_card_image_size) - } - if (cardRadius == 0f) { - cardRadius = service.resources.getDimension(code.name.monkey.retromusic.R.dimen.app_widget_card_radius) - } - val appContext = service.applicationContext - // Load the album cover async and push the update on completion - service.runOnUiThread { - if (target != null) { - Glide.clear(target) - } - target = SongGlideRequest.Builder.from(Glide.with(service), song) - .checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop() - .into(object : SimpleTarget(imageSize, imageSize) { - override fun onResourceReady( - resource: BitmapPaletteWrapper, - glideAnimation: GlideAnimation - ) { - val palette = resource.palette - update( - resource.bitmap, palette.getVibrantColor( - palette.getMutedColor( - MaterialValueHelper.getSecondaryTextColor( - service, true - ) - ) - ) - ) - } + if (imageSize == 0) { + imageSize = + service.resources.getDimensionPixelSize(code.name.monkey.retromusic.R.dimen.app_widget_card_image_size) + } + if (cardRadius == 0f) { + cardRadius = + service.resources.getDimension(code.name.monkey.retromusic.R.dimen.app_widget_card_radius) + } + val appContext = service.applicationContext + // Load the album cover async and push the update on completion + service.runOnUiThread { + if (target != null) { + Glide.clear(target) + } + target = SongGlideRequest.Builder.from(Glide.with(service), song) + .checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop() + .into(object : SimpleTarget(imageSize, imageSize) { + override fun onResourceReady( + resource: BitmapPaletteWrapper, + glideAnimation: GlideAnimation + ) { + val palette = resource.palette + update( + resource.bitmap, palette.getVibrantColor( + palette.getMutedColor( + MaterialValueHelper.getSecondaryTextColor( + service, true + ) + ) + ) + ) + } - override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { - super.onLoadFailed(e, errorDrawable) - update(null, MaterialValueHelper.getSecondaryTextColor(service, true)) - } + override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { + super.onLoadFailed(e, errorDrawable) + update(null, MaterialValueHelper.getSecondaryTextColor(service, true)) + } - private fun update(bitmap: Bitmap?, color: Int) { - // Set correct drawable for pause state - appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, ImageUtil.createBitmap( - ImageUtil.getTintedVectorDrawable( - service, playPauseRes, color - ) - ) - ) + private fun update(bitmap: Bitmap?, color: Int) { + // Set correct drawable for pause state + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, ImageUtil.createBitmap( + ImageUtil.getTintedVectorDrawable( + service, playPauseRes, color + ) + ) + ) - // Set prev/next button drawables - appWidgetView.setImageViewBitmap( - R.id.button_next, ImageUtil.createBitmap( - ImageUtil.getTintedVectorDrawable( - service, R.drawable.ic_skip_next_white_24dp, color - ) - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_prev, ImageUtil.createBitmap( - ImageUtil.getTintedVectorDrawable( - service, R.drawable.ic_skip_previous_white_24dp, color - ) - ) - ) + // Set prev/next button drawables + appWidgetView.setImageViewBitmap( + R.id.button_next, ImageUtil.createBitmap( + ImageUtil.getTintedVectorDrawable( + service, R.drawable.ic_skip_next_white_24dp, color + ) + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_prev, ImageUtil.createBitmap( + ImageUtil.getTintedVectorDrawable( + service, R.drawable.ic_skip_previous_white_24dp, color + ) + ) + ) - val image = getAlbumArtDrawable(service.resources, bitmap) - val roundedBitmap = createRoundedBitmap( - image, imageSize, imageSize, cardRadius, 0F, cardRadius, 0F - ) - appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap) + val image = getAlbumArtDrawable(service.resources, bitmap) + val roundedBitmap = createRoundedBitmap( + image, imageSize, imageSize, cardRadius, 0F, cardRadius, 0F + ) + appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap) - pushUpdate(service, appWidgetIds, appWidgetView) - } - }) - } - } + pushUpdate(service, appWidgetIds, appWidgetView) + } + }) + } + } - /** - * Link up various button actions using [PendingIntent]. - */ - private fun linkButtons(context: Context, views: RemoteViews) { - val action: Intent = Intent(context, MainActivity::class.java).putExtra("expand", true) - var pendingIntent: PendingIntent + /** + * Link up various button actions using [PendingIntent]. + */ + private fun linkButtons(context: Context, views: RemoteViews) { + val action: Intent = Intent(context, MainActivity::class.java).putExtra("expand", true) + var pendingIntent: PendingIntent - val serviceName = ComponentName(context, MusicService::class.java) + val serviceName = ComponentName(context, MusicService::class.java) - // Home - action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - pendingIntent = PendingIntent.getActivity(context, 0, action, 0) - views.setOnClickPendingIntent(R.id.image, pendingIntent) - views.setOnClickPendingIntent(R.id.media_titles, pendingIntent) + // Home + action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + pendingIntent = PendingIntent.getActivity(context, 0, action, 0) + views.setOnClickPendingIntent(R.id.image, pendingIntent) + views.setOnClickPendingIntent(R.id.media_titles, pendingIntent) - // Previous track - pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName) - views.setOnClickPendingIntent(R.id.button_prev, pendingIntent) + // Previous track + pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName) + views.setOnClickPendingIntent(R.id.button_prev, pendingIntent) - // Play and pause - pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName) - views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent) + // Play and pause + pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName) + views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent) - // Next track - pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName) - views.setOnClickPendingIntent(R.id.button_next, pendingIntent) - } + // Next track + pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName) + views.setOnClickPendingIntent(R.id.button_next, pendingIntent) + } - companion object { + companion object { - const val NAME = "app_widget_card" + const val NAME = "app_widget_card" - private var mInstance: AppWidgetCard? = null - private var imageSize = 0 - private var cardRadius = 0f + private var mInstance: AppWidgetCard? = null + private var imageSize = 0 + private var cardRadius = 0f - val instance: AppWidgetCard - @Synchronized get() { - if (mInstance == null) { - mInstance = AppWidgetCard() - } - return mInstance!! - } - } + val instance: AppWidgetCard + @Synchronized get() { + if (mInstance == null) { + mInstance = AppWidgetCard() + } + return mInstance!! + } + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetClassic.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetClassic.kt index 24f24c09..a8581501 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetClassic.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetClassic.kt @@ -31,9 +31,7 @@ import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget import code.name.monkey.retromusic.glide.SongGlideRequest import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper import code.name.monkey.retromusic.service.MusicService -import code.name.monkey.retromusic.service.MusicService.ACTION_REWIND -import code.name.monkey.retromusic.service.MusicService.ACTION_SKIP -import code.name.monkey.retromusic.service.MusicService.ACTION_TOGGLE_PAUSE +import code.name.monkey.retromusic.service.MusicService.* import code.name.monkey.retromusic.util.ImageUtil import code.name.monkey.retromusic.util.RetroUtil import com.bumptech.glide.Glide @@ -111,7 +109,8 @@ class AppWidgetClassic : BaseAppWidget() { linkButtons(service, appWidgetView) if (imageSize == 0) { - imageSize = service.resources.getDimensionPixelSize(R.dimen.app_widget_classic_image_size) + imageSize = + service.resources.getDimensionPixelSize(R.dimen.app_widget_classic_image_size) } if (cardRadius == 0f) { cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius) @@ -155,7 +154,13 @@ class AppWidgetClassic : BaseAppWidget() { if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_24dp appWidgetView.setImageViewBitmap( R.id.button_toggle_play_pause, - ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(service, playPauseRes, color)) + ImageUtil.createBitmap( + ImageUtil.getTintedVectorDrawable( + service, + playPauseRes, + color + ) + ) ) // Set prev/next button drawables @@ -182,7 +187,15 @@ class AppWidgetClassic : BaseAppWidget() { val image = getAlbumArtDrawable(service.resources, bitmap) val roundedBitmap = - createRoundedBitmap(image, imageSize, imageSize, cardRadius, 0F, cardRadius, 0F) + createRoundedBitmap( + image, + imageSize, + imageSize, + cardRadius, + 0F, + cardRadius, + 0F + ) appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap) pushUpdate(appContext, appWidgetIds, appWidgetView) diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetSmall.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetSmall.kt index 53715e96..0eae1a4e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetSmall.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetSmall.kt @@ -49,9 +49,36 @@ class AppWidgetSmall : BaseAppWidget() { appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE) appWidgetView.setImageViewResource(R.id.image, R.drawable.default_audio_art) - appWidgetView.setImageViewBitmap(R.id.button_next, createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_next_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f)) - appWidgetView.setImageViewBitmap(R.id.button_prev, createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_previous_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f)) - appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_play_arrow_white_32dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f)) + appWidgetView.setImageViewBitmap( + R.id.button_next, + createBitmap( + RetroUtil.getTintedVectorDrawable( + context, + R.drawable.ic_skip_next_white_24dp, + MaterialValueHelper.getSecondaryTextColor(context, true) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_prev, + createBitmap( + RetroUtil.getTintedVectorDrawable( + context, + R.drawable.ic_skip_previous_white_24dp, + MaterialValueHelper.getSecondaryTextColor(context, true) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, + createBitmap( + RetroUtil.getTintedVectorDrawable( + context, + R.drawable.ic_play_arrow_white_32dp, + MaterialValueHelper.getSecondaryTextColor(context, true) + )!!, 1f + ) + ) linkButtons(context, appWidgetView) pushUpdate(context, appWidgetIds, appWidgetView) @@ -98,66 +125,66 @@ class AppWidgetSmall : BaseAppWidget() { Glide.clear(target) } target = SongGlideRequest.Builder.from(Glide.with(service), song) - .checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop() - .into(object : SimpleTarget(imageSize, imageSize) { - override fun onResourceReady( - resource: BitmapPaletteWrapper, - glideAnimation: GlideAnimation - ) { - val palette = resource.palette - update( - resource.bitmap, palette.getVibrantColor( - palette.getMutedColor( - MaterialValueHelper.getSecondaryTextColor( - service, true - ) + .checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop() + .into(object : SimpleTarget(imageSize, imageSize) { + override fun onResourceReady( + resource: BitmapPaletteWrapper, + glideAnimation: GlideAnimation + ) { + val palette = resource.palette + update( + resource.bitmap, palette.getVibrantColor( + palette.getMutedColor( + MaterialValueHelper.getSecondaryTextColor( + service, true ) + ) ) - ) - } + ) + } - override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { - super.onLoadFailed(e, errorDrawable) - update(null, MaterialValueHelper.getSecondaryTextColor(service, true)) - } + override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { + super.onLoadFailed(e, errorDrawable) + update(null, MaterialValueHelper.getSecondaryTextColor(service, true)) + } - private fun update(bitmap: Bitmap?, color: Int) { - // Set correct drawable for pause state - val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp - else R.drawable.ic_play_arrow_white_32dp - appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, createBitmap( - RetroUtil.getTintedVectorDrawable( - service, playPauseRes, color - )!!, 1f - ) + private fun update(bitmap: Bitmap?, color: Int) { + // Set correct drawable for pause state + val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp + else R.drawable.ic_play_arrow_white_32dp + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, playPauseRes, color + )!!, 1f ) + ) - // Set prev/next button drawables - appWidgetView.setImageViewBitmap( - R.id.button_next, createBitmap( - RetroUtil.getTintedVectorDrawable( - service, R.drawable.ic_skip_next_white_24dp, color - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_prev, createBitmap( - RetroUtil.getTintedVectorDrawable( - service, R.drawable.ic_skip_previous_white_24dp, color - )!!, 1f + // Set prev/next button drawables + appWidgetView.setImageViewBitmap( + R.id.button_next, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, R.drawable.ic_skip_next_white_24dp, color + )!!, 1f ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_prev, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, R.drawable.ic_skip_previous_white_24dp, color + )!!, 1f ) + ) - val image = getAlbumArtDrawable(service.resources, bitmap) - val roundedBitmap = createRoundedBitmap( - image, imageSize, imageSize, cardRadius, 0f, 0f, 0f - ) - appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap) + val image = getAlbumArtDrawable(service.resources, bitmap) + val roundedBitmap = createRoundedBitmap( + image, imageSize, imageSize, cardRadius, 0f, 0f, 0f + ) + appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap) - pushUpdate(appContext, appWidgetIds, appWidgetView) - } - }) + pushUpdate(appContext, appWidgetIds, appWidgetView) + } + }) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetText.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetText.kt index 88bba6a8..c47136e6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetText.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetText.kt @@ -15,12 +15,15 @@ package code.name.monkey.retromusic.appwidgets import android.app.PendingIntent -import android.content.* +import android.content.ComponentName +import android.content.Context +import android.content.Intent import android.text.TextUtils import android.view.View import android.widget.RemoteViews import androidx.core.content.ContextCompat -import code.name.monkey.retromusic.* +import code.name.monkey.retromusic.App +import code.name.monkey.retromusic.R import code.name.monkey.retromusic.activities.MainActivity import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget import code.name.monkey.retromusic.service.MusicService @@ -28,146 +31,146 @@ import code.name.monkey.retromusic.service.MusicService.* import code.name.monkey.retromusic.util.RetroUtil class AppWidgetText : BaseAppWidget() { - override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) { - val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_text) + override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) { + val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_text) - appWidgetView.setImageViewBitmap( - R.id.button_next, createBitmap( - RetroUtil.getTintedVectorDrawable( - context, R.drawable.ic_skip_next_white_24dp, ContextCompat.getColor( - context, R.color.md_white_1000 - ) - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_prev, createBitmap( - RetroUtil.getTintedVectorDrawable( - context, R.drawable.ic_skip_previous_white_24dp, ContextCompat.getColor( - context, R.color.md_white_1000 - ) - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, createBitmap( - RetroUtil.getTintedVectorDrawable( - context, R.drawable.ic_play_arrow_white_32dp, ContextCompat.getColor( - context, R.color.md_white_1000 - ) - )!!, 1f - ) - ) + appWidgetView.setImageViewBitmap( + R.id.button_next, createBitmap( + RetroUtil.getTintedVectorDrawable( + context, R.drawable.ic_skip_next_white_24dp, ContextCompat.getColor( + context, R.color.md_white_1000 + ) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_prev, createBitmap( + RetroUtil.getTintedVectorDrawable( + context, R.drawable.ic_skip_previous_white_24dp, ContextCompat.getColor( + context, R.color.md_white_1000 + ) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, createBitmap( + RetroUtil.getTintedVectorDrawable( + context, R.drawable.ic_play_arrow_white_32dp, ContextCompat.getColor( + context, R.color.md_white_1000 + ) + )!!, 1f + ) + ) - appWidgetView.setTextColor( - R.id.title, ContextCompat.getColor(context, R.color.md_white_1000) - ) - appWidgetView.setTextColor( - R.id.text, ContextCompat.getColor(context, R.color.md_white_1000) - ) + appWidgetView.setTextColor( + R.id.title, ContextCompat.getColor(context, R.color.md_white_1000) + ) + appWidgetView.setTextColor( + R.id.text, ContextCompat.getColor(context, R.color.md_white_1000) + ) - linkButtons(context, appWidgetView) - pushUpdate(context, appWidgetIds, appWidgetView) - } + linkButtons(context, appWidgetView) + pushUpdate(context, appWidgetIds, appWidgetView) + } - /** - * Link up various button actions using [PendingIntent]. - */ - private fun linkButtons(context: Context, views: RemoteViews) { - val action = Intent(context, MainActivity::class.java).putExtra("expand", true) - var pendingIntent: PendingIntent + /** + * Link up various button actions using [PendingIntent]. + */ + private fun linkButtons(context: Context, views: RemoteViews) { + val action = Intent(context, MainActivity::class.java).putExtra("expand", true) + var pendingIntent: PendingIntent - val serviceName = ComponentName(context, MusicService::class.java) + val serviceName = ComponentName(context, MusicService::class.java) - // Home - action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - pendingIntent = PendingIntent.getActivity(context, 0, action, 0) - views.setOnClickPendingIntent(R.id.image, pendingIntent) - views.setOnClickPendingIntent(R.id.media_titles, pendingIntent) + // Home + action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + pendingIntent = PendingIntent.getActivity(context, 0, action, 0) + views.setOnClickPendingIntent(R.id.image, pendingIntent) + views.setOnClickPendingIntent(R.id.media_titles, pendingIntent) - // Previous track - pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName) - views.setOnClickPendingIntent(R.id.button_prev, pendingIntent) + // Previous track + pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName) + views.setOnClickPendingIntent(R.id.button_prev, pendingIntent) - // Play and pause - pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName) - views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent) + // Play and pause + pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName) + views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent) - // Next track - pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName) - views.setOnClickPendingIntent(R.id.button_next, pendingIntent) - } + // Next track + pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName) + views.setOnClickPendingIntent(R.id.button_next, pendingIntent) + } - override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) { - val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_text) + override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) { + val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_text) - val isPlaying = service.isPlaying - val song = service.currentSong + val isPlaying = service.isPlaying + val song = service.currentSong - // Set the titles and artwork - if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) { - appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE) - } else { - appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE) - appWidgetView.setTextViewText(R.id.title, song.title) - appWidgetView.setTextViewText(R.id.text, song.artistName) - } - // Link actions buttons to intents - linkButtons(service, appWidgetView) + // Set the titles and artwork + if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) { + appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE) + } else { + appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE) + appWidgetView.setTextViewText(R.id.title, song.title) + appWidgetView.setTextViewText(R.id.text, song.artistName) + } + // Link actions buttons to intents + linkButtons(service, appWidgetView) - // Set correct drawable for pause state - val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp - else R.drawable.ic_play_arrow_white_32dp - appWidgetView.setImageViewBitmap( - R.id.button_toggle_play_pause, createBitmap( - RetroUtil.getTintedVectorDrawable( - App.getContext(), playPauseRes, ContextCompat.getColor( - App.getContext(), R.color.md_white_1000 - ) - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_next, createBitmap( - RetroUtil.getTintedVectorDrawable( - App.getContext(), - R.drawable.ic_skip_next_white_24dp, - ContextCompat.getColor( - App.getContext(), R.color.md_white_1000 - ) - )!!, 1f - ) - ) - appWidgetView.setImageViewBitmap( - R.id.button_prev, createBitmap( - RetroUtil.getTintedVectorDrawable( - App.getContext(), - R.drawable.ic_skip_previous_white_24dp, - ContextCompat.getColor( - App.getContext(), R.color.md_white_1000 - ) - )!!, 1f - ) - ) + // Set correct drawable for pause state + val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp + else R.drawable.ic_play_arrow_white_32dp + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, createBitmap( + RetroUtil.getTintedVectorDrawable( + App.getContext(), playPauseRes, ContextCompat.getColor( + App.getContext(), R.color.md_white_1000 + ) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_next, createBitmap( + RetroUtil.getTintedVectorDrawable( + App.getContext(), + R.drawable.ic_skip_next_white_24dp, + ContextCompat.getColor( + App.getContext(), R.color.md_white_1000 + ) + )!!, 1f + ) + ) + appWidgetView.setImageViewBitmap( + R.id.button_prev, createBitmap( + RetroUtil.getTintedVectorDrawable( + App.getContext(), + R.drawable.ic_skip_previous_white_24dp, + ContextCompat.getColor( + App.getContext(), R.color.md_white_1000 + ) + )!!, 1f + ) + ) - pushUpdate(service.applicationContext, appWidgetIds, appWidgetView) + pushUpdate(service.applicationContext, appWidgetIds, appWidgetView) - } + } - companion object { + companion object { - const val NAME: String = "app_widget_text" + const val NAME: String = "app_widget_text" - private var mInstance: AppWidgetText? = null + private var mInstance: AppWidgetText? = null - val instance: AppWidgetText - @Synchronized get() { - if (mInstance == null) { - mInstance = AppWidgetText() - } - return mInstance!! - } - } + val instance: AppWidgetText + @Synchronized get() { + if (mInstance == null) { + mInstance = AppWidgetText() + } + return mInstance!! + } + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/BootReceiver.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/BootReceiver.kt index 90a9cf8a..5f82c2af 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appwidgets/BootReceiver.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/BootReceiver.kt @@ -15,36 +15,40 @@ package code.name.monkey.retromusic.appwidgets import android.appwidget.AppWidgetManager -import android.content.* +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.Context +import android.content.Intent import android.os.Build import code.name.monkey.retromusic.service.MusicService class BootReceiver : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - val widgetManager = AppWidgetManager.getInstance(context) + override fun onReceive(context: Context, intent: Intent) { + val widgetManager = AppWidgetManager.getInstance(context) - // Start music service if there are any existing widgets - if (widgetManager.getAppWidgetIds( - ComponentName( - context, AppWidgetBig::class.java - ) - ).isNotEmpty() || widgetManager.getAppWidgetIds( - ComponentName( - context, AppWidgetClassic::class.java - ) - ).isNotEmpty() || widgetManager.getAppWidgetIds( - ComponentName( - context, AppWidgetSmall::class.java - ) - ).isNotEmpty() || widgetManager.getAppWidgetIds( - ComponentName( - context, AppWidgetCard::class.java - ) - ).isNotEmpty()) { - val serviceIntent = Intent(context, MusicService::class.java) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // not allowed on Oreo - context.startService(serviceIntent) - } - } - } + // Start music service if there are any existing widgets + if (widgetManager.getAppWidgetIds( + ComponentName( + context, AppWidgetBig::class.java + ) + ).isNotEmpty() || widgetManager.getAppWidgetIds( + ComponentName( + context, AppWidgetClassic::class.java + ) + ).isNotEmpty() || widgetManager.getAppWidgetIds( + ComponentName( + context, AppWidgetSmall::class.java + ) + ).isNotEmpty() || widgetManager.getAppWidgetIds( + ComponentName( + context, AppWidgetCard::class.java + ) + ).isNotEmpty() + ) { + val serviceIntent = Intent(context, MusicService::class.java) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // not allowed on Oreo + context.startService(serviceIntent) + } + } + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/base/BaseAppWidget.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/base/BaseAppWidget.kt index c8a2e905..29f0d748 100644 --- a/app/src/main/java/code/name/monkey/retromusic/appwidgets/base/BaseAppWidget.kt +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/base/BaseAppWidget.kt @@ -15,170 +15,175 @@ package code.name.monkey.retromusic.appwidgets.base import android.app.PendingIntent -import android.appwidget.* -import android.content.* +import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetProvider +import android.content.ComponentName +import android.content.Context +import android.content.Intent import android.content.res.Resources import android.graphics.* -import android.graphics.drawable.* +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable import android.os.Build import android.text.TextUtils import android.widget.RemoteViews import androidx.core.content.ContextCompat -import code.name.monkey.retromusic.* +import code.name.monkey.retromusic.App +import code.name.monkey.retromusic.R import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService.* abstract class BaseAppWidget : AppWidgetProvider() { - /** - * {@inheritDoc} - */ - override fun onUpdate( - context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray - ) { - defaultAppWidget(context, appWidgetIds) - val updateIntent = Intent(APP_WIDGET_UPDATE) - updateIntent.putExtra(EXTRA_APP_WIDGET_NAME, NAME) - updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds) - updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) - context.sendBroadcast(updateIntent) - } + /** + * {@inheritDoc} + */ + override fun onUpdate( + context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray + ) { + defaultAppWidget(context, appWidgetIds) + val updateIntent = Intent(APP_WIDGET_UPDATE) + updateIntent.putExtra(EXTRA_APP_WIDGET_NAME, NAME) + updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds) + updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) + context.sendBroadcast(updateIntent) + } - /** - * Handle a change notification coming over from [MusicService] - */ - fun notifyChange(service: MusicService, what: String) { - if (hasInstances(service)) { - if (META_CHANGED == what || PLAY_STATE_CHANGED == what) { - performUpdate(service, null) - } - } - } + /** + * Handle a change notification coming over from [MusicService] + */ + fun notifyChange(service: MusicService, what: String) { + if (hasInstances(service)) { + if (META_CHANGED == what || PLAY_STATE_CHANGED == what) { + performUpdate(service, null) + } + } + } - protected fun pushUpdate( - context: Context, appWidgetIds: IntArray?, views: RemoteViews - ) { - val appWidgetManager = AppWidgetManager.getInstance(context) - if (appWidgetIds != null) { - appWidgetManager.updateAppWidget(appWidgetIds, views) - } else { - appWidgetManager.updateAppWidget(ComponentName(context, javaClass), views) - } - } + protected fun pushUpdate( + context: Context, appWidgetIds: IntArray?, views: RemoteViews + ) { + val appWidgetManager = AppWidgetManager.getInstance(context) + if (appWidgetIds != null) { + appWidgetManager.updateAppWidget(appWidgetIds, views) + } else { + appWidgetManager.updateAppWidget(ComponentName(context, javaClass), views) + } + } - /** - * Check against [AppWidgetManager] if there are any instances of this widget. - */ - private fun hasInstances(context: Context): Boolean { - val appWidgetManager = AppWidgetManager.getInstance(context) - val mAppWidgetIds = appWidgetManager.getAppWidgetIds( - ComponentName( - context, javaClass - ) - ) - return mAppWidgetIds.isNotEmpty() - } + /** + * Check against [AppWidgetManager] if there are any instances of this widget. + */ + private fun hasInstances(context: Context): Boolean { + val appWidgetManager = AppWidgetManager.getInstance(context) + val mAppWidgetIds = appWidgetManager.getAppWidgetIds( + ComponentName( + context, javaClass + ) + ) + return mAppWidgetIds.isNotEmpty() + } - protected fun buildPendingIntent( - context: Context, action: String, serviceName: ComponentName - ): PendingIntent { - val intent = Intent(action) - intent.component = serviceName - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - PendingIntent.getForegroundService(context, 0, intent, 0) - } else { - PendingIntent.getService(context, 0, intent, 0) - } - } + protected fun buildPendingIntent( + context: Context, action: String, serviceName: ComponentName + ): PendingIntent { + val intent = Intent(action) + intent.component = serviceName + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + PendingIntent.getForegroundService(context, 0, intent, 0) + } else { + PendingIntent.getService(context, 0, intent, 0) + } + } - protected abstract fun defaultAppWidget(context: Context, appWidgetIds: IntArray) + protected abstract fun defaultAppWidget(context: Context, appWidgetIds: IntArray) - abstract fun performUpdate(service: MusicService, appWidgetIds: IntArray?) + abstract fun performUpdate(service: MusicService, appWidgetIds: IntArray?) - protected fun getAlbumArtDrawable(resources: Resources, bitmap: Bitmap?): Drawable { - return if (bitmap == null) { - ContextCompat.getDrawable(App.getContext(), R.drawable.default_audio_art)!! - } else { - BitmapDrawable(resources, bitmap) - } - } + protected fun getAlbumArtDrawable(resources: Resources, bitmap: Bitmap?): Drawable { + return if (bitmap == null) { + ContextCompat.getDrawable(App.getContext(), R.drawable.default_audio_art)!! + } else { + BitmapDrawable(resources, bitmap) + } + } - protected fun getSongArtistAndAlbum(song: Song): String { - val builder = StringBuilder() - builder.append(song.artistName) - if (!TextUtils.isEmpty(song.artistName) && !TextUtils.isEmpty(song.albumName)) { - builder.append(" • ") - } - builder.append(song.albumName) - return builder.toString() - } + protected fun getSongArtistAndAlbum(song: Song): String { + val builder = StringBuilder() + builder.append(song.artistName) + if (!TextUtils.isEmpty(song.artistName) && !TextUtils.isEmpty(song.albumName)) { + builder.append(" • ") + } + builder.append(song.albumName) + return builder.toString() + } - companion object { + companion object { - const val NAME: String = "app_widget" + const val NAME: String = "app_widget" - fun createRoundedBitmap( - drawable: Drawable?, - width: Int, - height: Int, - tl: Float, - tr: Float, - bl: Float, - br: Float - ): Bitmap? { - if (drawable == null) { - return null - } + fun createRoundedBitmap( + drawable: Drawable?, + width: Int, + height: Int, + tl: Float, + tr: Float, + bl: Float, + br: Float + ): Bitmap? { + if (drawable == null) { + return null + } - val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) - val c = Canvas(bitmap) - drawable.setBounds(0, 0, width, height) - drawable.draw(c) + val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + val c = Canvas(bitmap) + drawable.setBounds(0, 0, width, height) + drawable.draw(c) - val rounded = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + val rounded = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) - val canvas = Canvas(rounded) - val paint = Paint() - paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) - paint.isAntiAlias = true - canvas.drawPath( - composeRoundedRectPath( - RectF(0f, 0f, width.toFloat(), height.toFloat()), tl, tr, bl, br - ), paint - ) + val canvas = Canvas(rounded) + val paint = Paint() + paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) + paint.isAntiAlias = true + canvas.drawPath( + composeRoundedRectPath( + RectF(0f, 0f, width.toFloat(), height.toFloat()), tl, tr, bl, br + ), paint + ) - return rounded - } + return rounded + } - fun createBitmap(drawable: Drawable, sizeMultiplier: Float): Bitmap { - val bitmap = Bitmap.createBitmap( - (drawable.intrinsicWidth * sizeMultiplier).toInt(), - (drawable.intrinsicHeight * sizeMultiplier).toInt(), - Bitmap.Config.ARGB_8888 - ) - val c = Canvas(bitmap) - drawable.setBounds(0, 0, c.width, c.height) - drawable.draw(c) - return bitmap - } + fun createBitmap(drawable: Drawable, sizeMultiplier: Float): Bitmap { + val bitmap = Bitmap.createBitmap( + (drawable.intrinsicWidth * sizeMultiplier).toInt(), + (drawable.intrinsicHeight * sizeMultiplier).toInt(), + Bitmap.Config.ARGB_8888 + ) + val c = Canvas(bitmap) + drawable.setBounds(0, 0, c.width, c.height) + drawable.draw(c) + return bitmap + } - protected fun composeRoundedRectPath( - rect: RectF, tl: Float, tr: Float, bl: Float, br: Float - ): Path { - val path = Path() - path.moveTo(rect.left + tl, rect.top) - path.lineTo(rect.right - tr, rect.top) - path.quadTo(rect.right, rect.top, rect.right, rect.top + tr) - path.lineTo(rect.right, rect.bottom - br) - path.quadTo(rect.right, rect.bottom, rect.right - br, rect.bottom) - path.lineTo(rect.left + bl, rect.bottom) - path.quadTo(rect.left, rect.bottom, rect.left, rect.bottom - bl) - path.lineTo(rect.left, rect.top + tl) - path.quadTo(rect.left, rect.top, rect.left + tl, rect.top) - path.close() + protected fun composeRoundedRectPath( + rect: RectF, tl: Float, tr: Float, bl: Float, br: Float + ): Path { + val path = Path() + path.moveTo(rect.left + tl, rect.top) + path.lineTo(rect.right - tr, rect.top) + path.quadTo(rect.right, rect.top, rect.right, rect.top + tr) + path.lineTo(rect.right, rect.bottom - br) + path.quadTo(rect.right, rect.bottom, rect.right - br, rect.bottom) + path.lineTo(rect.left + bl, rect.bottom) + path.quadTo(rect.left, rect.bottom, rect.left, rect.bottom - bl) + path.lineTo(rect.left, rect.top + tl) + path.quadTo(rect.left, rect.top, rect.left + tl, rect.top) + path.close() - return path - } - } + return path + } + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt b/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt index efa9a1c5..361bb91a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt @@ -14,19 +14,10 @@ package code.name.monkey.retromusic.dagger -import code.name.monkey.retromusic.activities.AlbumDetailsActivity -import code.name.monkey.retromusic.activities.ArtistDetailActivity -import code.name.monkey.retromusic.activities.GenreDetailsActivity -import code.name.monkey.retromusic.activities.PlaylistDetailActivity -import code.name.monkey.retromusic.activities.SearchActivity +import code.name.monkey.retromusic.activities.* import code.name.monkey.retromusic.dagger.module.AppModule import code.name.monkey.retromusic.dagger.module.PresenterModule -import code.name.monkey.retromusic.fragments.mainactivity.AlbumsFragment -import code.name.monkey.retromusic.fragments.mainactivity.ArtistsFragment -import code.name.monkey.retromusic.fragments.mainactivity.GenresFragment -import code.name.monkey.retromusic.fragments.mainactivity.PlaylistsFragment -import code.name.monkey.retromusic.fragments.mainactivity.SongsFragment -import code.name.monkey.retromusic.fragments.mainactivity.BannerHomeFragment +import code.name.monkey.retromusic.fragments.mainactivity.* import dagger.Component import javax.inject.Singleton diff --git a/app/src/main/java/code/name/monkey/retromusic/dagger/module/PresenterModile.kt b/app/src/main/java/code/name/monkey/retromusic/dagger/module/PresenterModile.kt index 707f369c..880ecc88 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dagger/module/PresenterModile.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dagger/module/PresenterModile.kt @@ -15,27 +15,17 @@ package code.name.monkey.retromusic.dagger.module import android.content.Context -import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter +import code.name.monkey.retromusic.mvp.presenter.* import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter.AlbumDetailsPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter.AlbumsPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter.ArtistDetailsPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter.ArtistsPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter.GenreDetailsPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.GenresPresenter import code.name.monkey.retromusic.mvp.presenter.GenresPresenter.GenresPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.HomePresenter import code.name.monkey.retromusic.mvp.presenter.HomePresenter.HomePresenterImpl -import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter.PlaylistSongsPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter.PlaylistsPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.SearchPresenter import code.name.monkey.retromusic.mvp.presenter.SearchPresenter.SearchPresenterImpl -import code.name.monkey.retromusic.mvp.presenter.SongPresenter import code.name.monkey.retromusic.mvp.presenter.SongPresenter.SongPresenterImpl import code.name.monkey.retromusic.providers.RepositoryImpl import code.name.monkey.retromusic.providers.interfaces.Repository diff --git a/app/src/main/java/code/name/monkey/retromusic/deezer/DeezerApiService.kt b/app/src/main/java/code/name/monkey/retromusic/deezer/DeezerApiService.kt index d8f46796..95daf6bd 100644 --- a/app/src/main/java/code/name/monkey/retromusic/deezer/DeezerApiService.kt +++ b/app/src/main/java/code/name/monkey/retromusic/deezer/DeezerApiService.kt @@ -11,7 +11,7 @@ import retrofit2.create import retrofit2.http.GET import retrofit2.http.Query import java.io.File -import java.util.Locale +import java.util.* private const val BASE_QUERY_ARTIST = "search/artist" private const val BASE_URL = "https://api.deezer.com/" diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/AddToPlaylistDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/AddToPlaylistDialog.kt index 9ae8af57..c805bae2 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/AddToPlaylistDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/AddToPlaylistDialog.kt @@ -51,7 +51,12 @@ class AddToPlaylistDialog : DialogFragment() { } } else { dialog.dismiss() - PlaylistsUtil.addToPlaylist(requireContext(), songs, playlists[index - 1].id, true) + PlaylistsUtil.addToPlaylist( + requireContext(), + songs, + playlists[index - 1].id, + true + ) } } } diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt index be3b01d3..e91ed492 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt @@ -81,7 +81,11 @@ class BlacklistFolderChooserDialog : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { var savedInstanceStateFinal = savedInstanceState if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && - ActivityCompat.checkSelfPermission(requireActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.checkSelfPermission( + requireActivity(), + Manifest.permission.READ_EXTERNAL_STORAGE + ) != PackageManager.PERMISSION_GRANTED + ) { return MaterialDialog(requireActivity(), BottomSheet(LayoutMode.WRAP_CONTENT)).show { title(R.string.md_error_label) cornerRadius(PreferenceUtil.getInstance(requireContext()).dialogCorner) diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/CreatePlaylistDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/CreatePlaylistDialog.kt index 56318bfc..ab750306 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/CreatePlaylistDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/CreatePlaylistDialog.kt @@ -57,7 +57,10 @@ class CreatePlaylistDialog : DialogFragment() { ?: return@positiveButton if (playlistView.text.toString().trim { it <= ' ' }.isNotEmpty()) { - val playlistId = PlaylistsUtil.createPlaylist(requireContext(), playlistView.text.toString()) + val playlistId = PlaylistsUtil.createPlaylist( + requireContext(), + playlistView.text.toString() + ) if (playlistId != -1 && activity != null) { PlaylistsUtil.addToPlaylist(requireContext(), songs, playlistId, true) } @@ -73,7 +76,10 @@ class CreatePlaylistDialog : DialogFragment() { val playlistId = arguments!!.getLong(MediaStore.Audio.Playlists.Members.PLAYLIST_ID) playlistView.appHandleColor() - .setText(PlaylistsUtil.getNameForPlaylist(requireContext(), playlistId), TextView.BufferType.EDITABLE) + .setText( + PlaylistsUtil.getNameForPlaylist(requireContext(), playlistId), + TextView.BufferType.EDITABLE + ) return materialDialog } diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/DeletePlaylistDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/DeletePlaylistDialog.kt index 6e022020..76535bb8 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/DeletePlaylistDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/DeletePlaylistDialog.kt @@ -26,7 +26,7 @@ import code.name.monkey.retromusic.util.PreferenceUtil import com.afollestad.materialdialogs.LayoutMode import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.bottomsheets.BottomSheet -import java.util.ArrayList +import java.util.* class DeletePlaylistDialog : DialogFragment() { diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsAsyncTask.java b/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsAsyncTask.java index 70b70780..e55488c7 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsAsyncTask.java +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsAsyncTask.java @@ -21,54 +21,29 @@ import android.content.Intent; import android.net.Uri; import android.os.Build; import android.util.Log; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; + +import com.google.android.material.dialog.MaterialAlertDialogBuilder; + +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.List; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.activities.saf.SAFGuideActivity; import code.name.monkey.retromusic.misc.DialogAsyncTask; import code.name.monkey.retromusic.model.Song; import code.name.monkey.retromusic.util.SAFUtil; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.List; /** * Created by hemanths on 2019-07-31. */ public class DeleteSongsAsyncTask extends DialogAsyncTask { - public static class LoadingInfo { - - public Intent intent; - - public boolean isIntent; - - public int requestCode; - - public int resultCode; - - public List safUris; - - public List songs; - - public LoadingInfo(List songs, List safUris) { - this.isIntent = false; - this.songs = songs; - this.safUris = safUris; - } - - public LoadingInfo(int requestCode, int resultCode, Intent intent) { - this.isIntent = true; - this.requestCode = requestCode; - this.resultCode = resultCode; - this.intent = intent; - } - } - private WeakReference activityWeakReference; - private WeakReference dialogReference; public DeleteSongsAsyncTask(@NonNull DeleteSongsDialog dialog) { @@ -138,4 +113,32 @@ public class DeleteSongsAsyncTask extends DialogAsyncTask safUris; + + public List songs; + + public LoadingInfo(List songs, List safUris) { + this.isIntent = false; + this.songs = songs; + this.safUris = safUris; + } + + public LoadingInfo(int requestCode, int resultCode, Intent intent) { + this.isIntent = true; + this.requestCode = requestCode; + this.resultCode = resultCode; + this.intent = intent; + } + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsDialog.kt index 902c245e..aa9b0d68 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/DeleteSongsDialog.kt @@ -87,7 +87,13 @@ class DeleteSongsDialog : DialogFragment() { deleteSongsAsyncTask?.cancel(true) } deleteSongsAsyncTask = DeleteSongsAsyncTask(this) - deleteSongsAsyncTask?.execute(DeleteSongsAsyncTask.LoadingInfo(requestCode, resultCode, data)) + deleteSongsAsyncTask?.execute( + DeleteSongsAsyncTask.LoadingInfo( + requestCode, + resultCode, + data + ) + ) } } } diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/OptionsSheetDialogFragment.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/OptionsSheetDialogFragment.kt index 28434ecb..3f6140af 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/OptionsSheetDialogFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/OptionsSheetDialogFragment.kt @@ -74,7 +74,11 @@ class OptionsSheetDialogFragment : DialogFragment(), View.OnClickListener { return materialDialog } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { dialog?.window?.let { (requireActivity() as MainActivity).setNavigationbarColorAuto() (requireActivity() as MainActivity).setLightNavigationBar(true) diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/RenamePlaylistDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/RenamePlaylistDialog.kt index c0df8987..ca123feb 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/RenamePlaylistDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/RenamePlaylistDialog.kt @@ -48,7 +48,11 @@ class RenamePlaylistDialog : DialogFragment() { positiveButton(string.action_rename) { if (playlistView.toString().trim { it <= ' ' } != "") { val playlistId = arguments!!.getLong(PLAYLIST_ID) - PlaylistsUtil.renamePlaylist(context, playlistId, playlistView.text!!.toString()) + PlaylistsUtil.renamePlaylist( + context, + playlistId, + playlistView.text!!.toString() + ) } } } @@ -61,7 +65,10 @@ class RenamePlaylistDialog : DialogFragment() { val playlistId = arguments!!.getLong(PLAYLIST_ID) playlistView.appHandleColor() - .setText(PlaylistsUtil.getNameForPlaylist(context!!, playlistId), TextView.BufferType.EDITABLE) + .setText( + PlaylistsUtil.getNameForPlaylist(context!!, playlistId), + TextView.BufferType.EDITABLE + ) return materialDialog } diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt index 11ff4a36..d469bf0c 100755 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt @@ -62,7 +62,8 @@ class SleepTimerDialog : DialogFragment() { .title(R.string.action_sleep_timer) .cornerRadius(PreferenceUtil.getInstance(requireContext()).dialogCorner) .positiveButton(R.string.action_set) { - PreferenceUtil.getInstance(requireContext()).sleepTimerFinishMusic = shouldFinishLastSong.isChecked + PreferenceUtil.getInstance(requireContext()).sleepTimerFinishMusic = + shouldFinishLastSong.isChecked val minutes = seekArcProgress @@ -119,10 +120,15 @@ class SleepTimerDialog : DialogFragment() { return materialDialog } - shouldFinishLastSong = materialDialog.getCustomView().findViewById(R.id.shouldFinishLastSong) + shouldFinishLastSong = + materialDialog.getCustomView().findViewById(R.id.shouldFinishLastSong) seekBar = materialDialog.getCustomView().findViewById(R.id.seekBar) timerDisplay = materialDialog.getCustomView().findViewById(R.id.timerDisplay) - TintHelper.setTintAuto(shouldFinishLastSong, ThemeStore.accentColor(requireContext()), false) + TintHelper.setTintAuto( + shouldFinishLastSong, + ThemeStore.accentColor(requireContext()), + false + ) val finishMusic = PreferenceUtil.getInstance(requireContext()).sleepTimerFinishMusic shouldFinishLastSong.isChecked = finishMusic diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/SongDetailDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/SongDetailDialog.kt index d8620ada..4db8bb86 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/SongDetailDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/SongDetailDialog.kt @@ -86,22 +86,36 @@ class SongDetailDialog : DialogFragment() { val songFile = File(song.data) if (songFile.exists()) { fileName.text = makeTextWithTitle(context, string.label_file_name, songFile.name) - filePath.text = makeTextWithTitle(context, string.label_file_path, songFile.absolutePath) + filePath.text = + makeTextWithTitle(context, string.label_file_path, songFile.absolutePath) fileSize.text = - makeTextWithTitle(context, string.label_file_size, getFileSizeString(songFile.length())) + makeTextWithTitle( + context, + string.label_file_size, + getFileSizeString(songFile.length()) + ) try { val audioFile = AudioFileIO.read(songFile) val audioHeader = audioFile.audioHeader - fileFormat.text = makeTextWithTitle(context, string.label_file_format, audioHeader.format) + fileFormat.text = + makeTextWithTitle(context, string.label_file_format, audioHeader.format) trackLength.text = makeTextWithTitle( context, string.label_track_length, MusicUtil.getReadableDurationString((audioHeader.trackLength * 1000).toLong()) ) - bitRate.text = makeTextWithTitle(context, string.label_bit_rate, audioHeader.bitRate + " kb/s") + bitRate.text = makeTextWithTitle( + context, + string.label_bit_rate, + audioHeader.bitRate + " kb/s" + ) samplingRate.text = - makeTextWithTitle(context, string.label_sampling_rate, audioHeader.sampleRate + " Hz") + makeTextWithTitle( + context, + string.label_sampling_rate, + audioHeader.sampleRate + " Hz" + ) } catch (@NonNull e: CannotReadException) { Log.e(TAG, "error while reading the song file", e) // fallback diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/SongShareDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/SongShareDialog.kt index f57b92cb..dc26f98a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/SongShareDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/SongShareDialog.kt @@ -68,7 +68,10 @@ class SongShareDialog : DialogFragment() { 2 -> { if (song != null) { startActivity( - Intent(requireContext(), ShareInstagramStory::class.java).putExtra( + Intent( + requireContext(), + ShareInstagramStory::class.java + ).putExtra( ShareInstagramStory.EXTRA_SONG, song ) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/AlbumCoverStyle.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/AlbumCoverStyle.kt index 48764425..94087932 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/AlbumCoverStyle.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/AlbumCoverStyle.kt @@ -5,10 +5,12 @@ import androidx.annotation.StringRes import code.name.monkey.retromusic.R -enum class AlbumCoverStyle(@param:StringRes @field:StringRes - val titleRes: Int, - @param:DrawableRes @field:DrawableRes - val drawableResId: Int, val id: Int) { +enum class AlbumCoverStyle( + @param:StringRes @field:StringRes + val titleRes: Int, + @param:DrawableRes @field:DrawableRes + val drawableResId: Int, val id: Int +) { NORMAL(R.string.normal, R.drawable.np_normal, 0), FLAT(R.string.flat, R.drawable.np_flat, 1), CIRCLE(R.string.circular, R.drawable.np_circle, 2), diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/MiniPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/MiniPlayerFragment.kt index f19b2bd6..9efa2f46 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/MiniPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/MiniPlayerFragment.kt @@ -7,11 +7,7 @@ import android.os.Bundle import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan -import android.view.GestureDetector -import android.view.LayoutInflater -import android.view.MotionEvent -import android.view.View -import android.view.ViewGroup +import android.view.* import android.view.animation.DecelerateInterpolator import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.retromusic.R @@ -24,11 +20,7 @@ import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.ViewUtil -import kotlinx.android.synthetic.main.fragment_mini_player.actionNext -import kotlinx.android.synthetic.main.fragment_mini_player.actionPrevious -import kotlinx.android.synthetic.main.fragment_mini_player.miniPlayerPlayPauseButton -import kotlinx.android.synthetic.main.fragment_mini_player.miniPlayerTitle -import kotlinx.android.synthetic.main.fragment_mini_player.progressBar +import kotlinx.android.synthetic.main.fragment_mini_player.* import kotlin.math.abs open class MiniPlayerFragment : AbsMusicServiceFragment(), MusicProgressViewUpdateHelper.Callback, @@ -41,7 +33,11 @@ open class MiniPlayerFragment : AbsMusicServiceFragment(), MusicProgressViewUpda progressViewUpdateHelper = MusicProgressViewUpdateHelper(this) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_mini_player, container, false) } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt index c7900e5d..ca890310 100755 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt @@ -11,6 +11,7 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.retromusic.R +import code.name.monkey.retromusic.extensions.setRange import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.ViewUtil @@ -18,9 +19,7 @@ import code.name.monkey.retromusic.volume.AudioVolumeObserver import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener import com.google.android.material.slider.Slider import com.google.android.material.slider.Slider.OnChangeListener -import kotlinx.android.synthetic.main.fragment_volume.volumeDown -import kotlinx.android.synthetic.main.fragment_volume.volumeSeekBar -import kotlinx.android.synthetic.main.fragment_volume.volumeUp +import kotlinx.android.synthetic.main.fragment_volume.* class VolumeFragment : Fragment(), OnAudioVolumeChangedListener, View.OnClickListener, OnChangeListener { @@ -52,7 +51,8 @@ class VolumeFragment : Fragment(), OnAudioVolumeChangedListener, val audioManager = audioManager if (audioManager != null) { - volumeSeekBar.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat() + volumeSeekBar.valueTo = + audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat() volumeSeekBar.value = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat() } volumeSeekBar.addOnChangeListener(this) @@ -62,11 +62,10 @@ class VolumeFragment : Fragment(), OnAudioVolumeChangedListener, if (volumeSeekBar == null) { return } - if (maxVolume <= 0) { + if (maxVolume <= 0.0f) { return } - volumeSeekBar.valueTo = maxVolume - volumeSeekBar.valueFrom = currentVolume + volumeSeekBar.setRange(currentVolume, maxVolume) volumeDown.setImageResource(if (currentVolume == 0.0f) R.drawable.ic_volume_off_white_24dp else R.drawable.ic_volume_down_white_24dp) } @@ -110,7 +109,6 @@ class VolumeFragment : Fragment(), OnAudioVolumeChangedListener, fun setTintableColor(color: Int) { volumeDown.setColorFilter(color, PorterDuff.Mode.SRC_IN) volumeUp.setColorFilter(color, PorterDuff.Mode.SRC_IN) - //TintHelper.setTint(volumeSeekBar, color, false) ViewUtil.setProgressDrawable(volumeSeekBar, color, true) } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsMusicServiceFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsMusicServiceFragment.kt index 12573abb..3ec3fbad 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsMusicServiceFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsMusicServiceFragment.kt @@ -13,7 +13,7 @@ import code.name.monkey.retromusic.util.RetroUtil import org.jaudiotagger.audio.AudioFileIO import java.io.File import java.net.URLEncoder -import java.util.Locale +import java.util.* /** * Created by hemanths on 18/08/17. @@ -81,7 +81,8 @@ open class AbsMusicServiceFragment : Fragment(), MusicServiceEventListener { val uriFile = Uri.fromFile(file) string.append(getMimeType(uriFile.toString())).append(" • ") string.append(audioHeader.bitRate).append(" kb/s").append(" • ") - string.append(RetroUtil.frequencyCount(audioHeader.sampleRate.toInt())).append(" kHz") + string.append(RetroUtil.frequencyCount(audioHeader.sampleRate.toInt())) + .append(" kHz") string.toString() } catch (er: Exception) { " - " diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerControlsFragment.kt index 85017dbd..0ac2d8c8 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerControlsFragment.kt @@ -13,7 +13,8 @@ import code.name.monkey.retromusic.util.PreferenceUtil * Created by hemanths on 24/09/17. */ -abstract class AbsPlayerControlsFragment : AbsMusicServiceFragment(), MusicProgressViewUpdateHelper.Callback { +abstract class AbsPlayerControlsFragment : AbsMusicServiceFragment(), + MusicProgressViewUpdateHelper.Callback { protected abstract fun show() @@ -61,9 +62,11 @@ abstract class AbsPlayerControlsFragment : AbsMusicServiceFragment(), MusicProgr private fun hideVolumeIfAvailable() { if (PreferenceUtil.getInstance(requireContext()).volumeToggle) { - childFragmentManager.beginTransaction().replace(R.id.volumeFragmentContainer, VolumeFragment()).commit() + childFragmentManager.beginTransaction() + .replace(R.id.volumeFragmentContainer, VolumeFragment()).commit() childFragmentManager.executePendingTransactions() - volumeFragment = childFragmentManager.findFragmentById(R.id.volumeFragmentContainer) as VolumeFragment? + volumeFragment = + childFragmentManager.findFragmentById(R.id.volumeFragmentContainer) as VolumeFragment? } } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt index 019f2261..18f08379 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt @@ -18,25 +18,15 @@ import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.retromusic.R import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity -import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog -import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog -import code.name.monkey.retromusic.dialogs.DeleteSongsDialog -import code.name.monkey.retromusic.dialogs.SleepTimerDialog -import code.name.monkey.retromusic.dialogs.SongDetailDialog -import code.name.monkey.retromusic.dialogs.SongShareDialog +import code.name.monkey.retromusic.dialogs.* import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.interfaces.PaletteColorHolder import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.lyrics.Lyrics -import code.name.monkey.retromusic.util.LyricUtil -import code.name.monkey.retromusic.util.MusicUtil -import code.name.monkey.retromusic.util.NavigationUtil -import code.name.monkey.retromusic.util.PreferenceUtil -import code.name.monkey.retromusic.util.RetroUtil -import code.name.monkey.retromusic.util.RingtoneManager -import kotlinx.android.synthetic.main.shadow_statusbar_toolbar.statusBarShadow +import code.name.monkey.retromusic.util.* +import kotlinx.android.synthetic.main.shadow_statusbar_toolbar.* import java.io.FileNotFoundException abstract class AbsPlayerFragment : AbsMusicServiceFragment(), @@ -141,9 +131,13 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(), R.id.action_go_to_genre -> { val retriever = MediaMetadataRetriever() val trackUri = - ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.id.toLong()) + ContentUris.withAppendedId( + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + song.id.toLong() + ) retriever.setDataSource(activity, trackUri) - var genre: String? = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE) + var genre: String? = + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE) if (genre == null) { genre = "Not Specified" } @@ -204,10 +198,14 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(), else R.drawable.ic_favorite_border_white_24dp - val drawable = RetroUtil.getTintedVectorDrawable(requireContext(), res, toolbarIconColor()) + val drawable = + RetroUtil.getTintedVectorDrawable(requireContext(), res, toolbarIconColor()) if (playerToolbar() != null && playerToolbar()!!.menu.findItem(R.id.action_toggle_favorite) != null) - playerToolbar()!!.menu.findItem(R.id.action_toggle_favorite).setIcon(drawable).title = - if (isFavorite) getString(R.string.action_remove_from_favorites) else getString(R.string.action_add_to_favorites) + playerToolbar()!!.menu.findItem(R.id.action_toggle_favorite).setIcon(drawable) + .title = + if (isFavorite) getString(R.string.action_remove_from_favorites) else getString( + R.string.action_add_to_favorites + ) } }.execute(MusicPlayerRemote.currentSong) } @@ -224,7 +222,8 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(), override fun doInBackground(vararg params: Song): Lyrics? { try { - var data: String? = LyricUtil.getStringFromFile(params[0].title, params[0].artistName) + var data: String? = + LyricUtil.getStringFromFile(params[0].title, params[0].artistName) return if (TextUtils.isEmpty(data)) { data = MusicUtil.getLyrics(params[0]) return if (TextUtils.isEmpty(data)) { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/AlbumsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/AlbumsFragment.kt index 4130925e..32c374d7 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/AlbumsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/AlbumsFragment.kt @@ -14,7 +14,8 @@ import code.name.monkey.retromusic.mvp.presenter.AlbumsView import code.name.monkey.retromusic.util.PreferenceUtil import javax.inject.Inject -class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment(), +class AlbumsFragment : + AbsLibraryPagerRecyclerViewCustomGridSizeFragment(), AlbumsView, MainActivityFragmentCallbacks { @Inject @@ -118,7 +119,8 @@ class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment(), +class ArtistsFragment : + AbsLibraryPagerRecyclerViewCustomGridSizeFragment(), ArtistsView, MainActivityFragmentCallbacks { override fun handleBackPress(): Boolean { @@ -111,6 +112,7 @@ class ArtistsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment> { - public static class ListPathsAsyncTask extends - ListingFilesDialogAsyncTask { - - public static class LoadingInfo { - - public final File file; - - final FileFilter fileFilter; - - public LoadingInfo(File file, FileFilter fileFilter) { - this.file = file; - this.fileFilter = fileFilter; - } - } - - public interface OnPathsListedCallback { - - void onPathsListed(@NonNull String[] paths); - } - - private WeakReference onPathsListedCallbackWeakReference; - - public ListPathsAsyncTask(Context context, OnPathsListedCallback callback) { - super(context); - onPathsListedCallbackWeakReference = new WeakReference<>(callback); - } - - @Override - protected String[] doInBackground(LoadingInfo... params) { - try { - if (isCancelled() || checkCallbackReference() == null) { - return null; - } - - LoadingInfo info = params[0]; - - final String[] paths; - - if (info.file.isDirectory()) { - List files = FileUtil.listFilesDeep(info.file, info.fileFilter); - - if (isCancelled() || checkCallbackReference() == null) { - return null; - } - - paths = new String[files.size()]; - for (int i = 0; i < files.size(); i++) { - File f = files.get(i); - paths[i] = FileUtil.safeGetCanonicalPath(f); - - if (isCancelled() || checkCallbackReference() == null) { - return null; - } - } - } else { - paths = new String[1]; - paths[0] = info.file.getPath(); - } - - return paths; - } catch (Exception e) { - e.printStackTrace(); - cancel(false); - return null; - } - } - - @Override - protected void onPostExecute(String[] paths) { - super.onPostExecute(paths); - OnPathsListedCallback callback = checkCallbackReference(); - if (callback != null && paths != null) { - callback.onPathsListed(paths); - } - } - - @Override - protected void onPreExecute() { - super.onPreExecute(); - checkCallbackReference(); - } - - private OnPathsListedCallback checkCallbackReference() { - OnPathsListedCallback callback = onPathsListedCallbackWeakReference.get(); - if (callback == null) { - cancel(false); - } - return callback; - } - } - - private static class AsyncFileLoader extends WrappedAsyncTaskLoader> { - - private WeakReference fragmentWeakReference; - - AsyncFileLoader(FoldersFragment foldersFragment) { - super(Objects.requireNonNull(foldersFragment.getActivity())); - fragmentWeakReference = new WeakReference<>(foldersFragment); - } - - @Override - public List loadInBackground() { - FoldersFragment foldersFragment = fragmentWeakReference.get(); - File directory = null; - if (foldersFragment != null) { - BreadCrumbLayout.Crumb crumb = foldersFragment.getActiveCrumb(); - if (crumb != null) { - directory = crumb.getFile(); - } - } - if (directory != null) { - List files = FileUtil.listFiles(directory, AUDIO_FILE_FILTER); - Collections.sort(files, foldersFragment.getFileComparator()); - return files; - } else { - return new LinkedList<>(); - } - } - } - - private static class ListSongsAsyncTask - extends ListingFilesDialogAsyncTask> { - - static class LoadingInfo { - - final Comparator fileComparator; - - final FileFilter fileFilter; - - final List files; - - LoadingInfo(@NonNull List files, @NonNull FileFilter fileFilter, - @NonNull Comparator fileComparator) { - this.fileComparator = fileComparator; - this.fileFilter = fileFilter; - this.files = files; - } - } - - public interface OnSongsListedCallback { - - void onSongsListed(@NonNull ArrayList songs, Object extra); - } - - private WeakReference callbackWeakReference; - - private WeakReference contextWeakReference; - - private final Object extra; - - ListSongsAsyncTask(Context context, Object extra, OnSongsListedCallback callback) { - super(context); - this.extra = extra; - contextWeakReference = new WeakReference<>(context); - callbackWeakReference = new WeakReference<>(callback); - } - - @Override - protected ArrayList doInBackground(LoadingInfo... params) { - try { - LoadingInfo info = params[0]; - List files = FileUtil.listFilesDeep(info.files, info.fileFilter); - - if (isCancelled() || checkContextReference() == null - || checkCallbackReference() == null) { - return null; - } - - Collections.sort(files, info.fileComparator); - - Context context = checkContextReference(); - if (isCancelled() || context == null || checkCallbackReference() == null) { - return null; - } - - return FileUtil.matchFilesWithMediaStore(context, files); - } catch (Exception e) { - e.printStackTrace(); - cancel(false); - return null; - } - } - - @Override - protected void onPostExecute(ArrayList songs) { - super.onPostExecute(songs); - OnSongsListedCallback callback = checkCallbackReference(); - if (songs != null && callback != null) { - callback.onSongsListed(songs, extra); - } - } - - @Override - protected void onPreExecute() { - super.onPreExecute(); - checkCallbackReference(); - checkContextReference(); - } - - private OnSongsListedCallback checkCallbackReference() { - OnSongsListedCallback callback = callbackWeakReference.get(); - if (callback == null) { - cancel(false); - } - return callback; - } - - private Context checkContextReference() { - Context context = contextWeakReference.get(); - if (context == null) { - cancel(false); - } - return context; - } - } - - private static abstract class ListingFilesDialogAsyncTask extends - DialogAsyncTask { - - ListingFilesDialogAsyncTask(Context context) { - super(context); - } - - public ListingFilesDialogAsyncTask(Context context, int showDelay) { - super(context, showDelay); - } - - @Override - protected Dialog createDialog(@NonNull Context context) { - return new MaterialAlertDialogBuilder(context) - .setTitle(R.string.listing_files) - .setCancelable(false) - .setView(R.layout.loading) - .setOnCancelListener(dialog -> cancel(false)) - .setOnDismissListener(dialog -> cancel(false)) - .create(); - } - } - public static final String TAG = FoldersFragment.class.getSimpleName(); - public static final FileFilter AUDIO_FILE_FILTER = file -> !file.isHidden() && (file.isDirectory() || FileUtil.fileIsMimeType(file, "audio/*", MimeTypeMap.getSingleton()) || FileUtil.fileIsMimeType(file, "application/opus", MimeTypeMap.getSingleton()) || FileUtil.fileIsMimeType(file, "application/ogg", MimeTypeMap.getSingleton())); - private static final String PATH = "path"; - private static final String CRUMBS = "crumbs"; - private static final int LOADER_ID = LoaderIds.Companion.getFOLDERS_FRAGMENT(); - private SongFileAdapter adapter; - private BreadCrumbLayout breadCrumbs; - private MaterialCab cab; - private View coordinatorLayout, empty; - private TextView emojiText; - private Comparator fileComparator = (lhs, rhs) -> { if (lhs.isDirectory() && !rhs.isDirectory()) { return -1; @@ -349,9 +104,10 @@ public class FoldersFragment extends AbsMainActivityFragment implements (rhs.getName()); } }; - private RecyclerView recyclerView; + public FoldersFragment() { + } public static File getDefaultStartDirectory() { File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); @@ -381,14 +137,20 @@ public class FoldersFragment extends AbsMainActivityFragment implements return newInstance(PreferenceUtil.getInstance(context).getStartDirectory()); } - public FoldersFragment() { + private static File tryGetCanonicalFile(File file) { + try { + return file.getCanonicalFile(); + } catch (IOException e) { + e.printStackTrace(); + return file; + } } @NonNull @Override public View onCreateView(@NonNull LayoutInflater inflater, - ViewGroup container, - Bundle savedInstanceState) { + ViewGroup container, + Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_folder, container, false); initViews(view); return view; @@ -737,12 +499,240 @@ public class FoldersFragment extends AbsMainActivityFragment implements } } - private static File tryGetCanonicalFile(File file) { - try { - return file.getCanonicalFile(); - } catch (IOException e) { - e.printStackTrace(); - return file; + public static class ListPathsAsyncTask extends + ListingFilesDialogAsyncTask { + + private WeakReference onPathsListedCallbackWeakReference; + + public ListPathsAsyncTask(Context context, OnPathsListedCallback callback) { + super(context); + onPathsListedCallbackWeakReference = new WeakReference<>(callback); + } + + @Override + protected String[] doInBackground(LoadingInfo... params) { + try { + if (isCancelled() || checkCallbackReference() == null) { + return null; + } + + LoadingInfo info = params[0]; + + final String[] paths; + + if (info.file.isDirectory()) { + List files = FileUtil.listFilesDeep(info.file, info.fileFilter); + + if (isCancelled() || checkCallbackReference() == null) { + return null; + } + + paths = new String[files.size()]; + for (int i = 0; i < files.size(); i++) { + File f = files.get(i); + paths[i] = FileUtil.safeGetCanonicalPath(f); + + if (isCancelled() || checkCallbackReference() == null) { + return null; + } + } + } else { + paths = new String[1]; + paths[0] = info.file.getPath(); + } + + return paths; + } catch (Exception e) { + e.printStackTrace(); + cancel(false); + return null; + } + } + + @Override + protected void onPostExecute(String[] paths) { + super.onPostExecute(paths); + OnPathsListedCallback callback = checkCallbackReference(); + if (callback != null && paths != null) { + callback.onPathsListed(paths); + } + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + checkCallbackReference(); + } + + private OnPathsListedCallback checkCallbackReference() { + OnPathsListedCallback callback = onPathsListedCallbackWeakReference.get(); + if (callback == null) { + cancel(false); + } + return callback; + } + + public interface OnPathsListedCallback { + + void onPathsListed(@NonNull String[] paths); + } + + public static class LoadingInfo { + + public final File file; + + final FileFilter fileFilter; + + public LoadingInfo(File file, FileFilter fileFilter) { + this.file = file; + this.fileFilter = fileFilter; + } + } + } + + private static class AsyncFileLoader extends WrappedAsyncTaskLoader> { + + private WeakReference fragmentWeakReference; + + AsyncFileLoader(FoldersFragment foldersFragment) { + super(Objects.requireNonNull(foldersFragment.getActivity())); + fragmentWeakReference = new WeakReference<>(foldersFragment); + } + + @Override + public List loadInBackground() { + FoldersFragment foldersFragment = fragmentWeakReference.get(); + File directory = null; + if (foldersFragment != null) { + BreadCrumbLayout.Crumb crumb = foldersFragment.getActiveCrumb(); + if (crumb != null) { + directory = crumb.getFile(); + } + } + if (directory != null) { + List files = FileUtil.listFiles(directory, AUDIO_FILE_FILTER); + Collections.sort(files, foldersFragment.getFileComparator()); + return files; + } else { + return new LinkedList<>(); + } + } + } + + private static class ListSongsAsyncTask + extends ListingFilesDialogAsyncTask> { + + private final Object extra; + private WeakReference callbackWeakReference; + private WeakReference contextWeakReference; + + ListSongsAsyncTask(Context context, Object extra, OnSongsListedCallback callback) { + super(context); + this.extra = extra; + contextWeakReference = new WeakReference<>(context); + callbackWeakReference = new WeakReference<>(callback); + } + + @Override + protected ArrayList doInBackground(LoadingInfo... params) { + try { + LoadingInfo info = params[0]; + List files = FileUtil.listFilesDeep(info.files, info.fileFilter); + + if (isCancelled() || checkContextReference() == null + || checkCallbackReference() == null) { + return null; + } + + Collections.sort(files, info.fileComparator); + + Context context = checkContextReference(); + if (isCancelled() || context == null || checkCallbackReference() == null) { + return null; + } + + return FileUtil.matchFilesWithMediaStore(context, files); + } catch (Exception e) { + e.printStackTrace(); + cancel(false); + return null; + } + } + + @Override + protected void onPostExecute(ArrayList songs) { + super.onPostExecute(songs); + OnSongsListedCallback callback = checkCallbackReference(); + if (songs != null && callback != null) { + callback.onSongsListed(songs, extra); + } + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + checkCallbackReference(); + checkContextReference(); + } + + private OnSongsListedCallback checkCallbackReference() { + OnSongsListedCallback callback = callbackWeakReference.get(); + if (callback == null) { + cancel(false); + } + return callback; + } + + private Context checkContextReference() { + Context context = contextWeakReference.get(); + if (context == null) { + cancel(false); + } + return context; + } + + public interface OnSongsListedCallback { + + void onSongsListed(@NonNull ArrayList songs, Object extra); + } + + static class LoadingInfo { + + final Comparator fileComparator; + + final FileFilter fileFilter; + + final List files; + + LoadingInfo(@NonNull List files, @NonNull FileFilter fileFilter, + @NonNull Comparator fileComparator) { + this.fileComparator = fileComparator; + this.fileFilter = fileFilter; + this.files = files; + } + } + } + + private static abstract class ListingFilesDialogAsyncTask extends + DialogAsyncTask { + + ListingFilesDialogAsyncTask(Context context) { + super(context); + } + + public ListingFilesDialogAsyncTask(Context context, int showDelay) { + super(context, showDelay); + } + + @Override + protected Dialog createDialog(@NonNull Context context) { + return new MaterialAlertDialogBuilder(context) + .setTitle(R.string.listing_files) + .setCancelable(false) + .setView(R.layout.loading) + .setOnCancelListener(dialog -> cancel(false)) + .setOnDismissListener(dialog -> cancel(false)) + .create(); } } } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/GenresFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/GenresFragment.kt index 46ebc440..bf0dc49c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/GenresFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/GenresFragment.kt @@ -85,6 +85,7 @@ class GenresFragment : AbsLibraryPagerRecyclerViewFragment(), +class PlayingQueueFragment : + AbsLibraryPagerRecyclerViewFragment(), MainActivityFragmentCallbacks { override fun handleBackPress(): Boolean { @@ -57,8 +58,10 @@ class PlayingQueueFragment : AbsLibraryPagerRecyclerViewFragment - wrappedAdapter = recyclerViewSwipeManager?.createWrappedAdapter(wrappedAdapter) as RecyclerView.Adapter<*> + wrappedAdapter = + recyclerViewDragDropManager?.createWrappedAdapter(adapter!!) as RecyclerView.Adapter<*> + wrappedAdapter = + recyclerViewSwipeManager?.createWrappedAdapter(wrappedAdapter) as RecyclerView.Adapter<*> recyclerView().layoutManager = layoutManager recyclerView().adapter = wrappedAdapter recyclerView().itemAnimator = animator @@ -137,6 +140,7 @@ class PlayingQueueFragment : AbsLibraryPagerRecyclerViewFragment(), PlaylistView, +class PlaylistsFragment : + AbsLibraryPagerRecyclerViewFragment(), PlaylistView, MainActivityFragmentCallbacks { override fun handleBackPress(): Boolean { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/SongsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/SongsFragment.kt index 66529505..10c12e76 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/SongsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/SongsFragment.kt @@ -14,10 +14,11 @@ import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.mvp.presenter.SongPresenter import code.name.monkey.retromusic.mvp.presenter.SongView import code.name.monkey.retromusic.util.PreferenceUtil -import java.util.ArrayList +import java.util.* import javax.inject.Inject -class SongsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment(), +class SongsFragment : + AbsLibraryPagerRecyclerViewCustomGridSizeFragment(), SongView, MainActivityFragmentCallbacks { @Inject diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/PlayerAlbumCoverFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/PlayerAlbumCoverFragment.kt index d1901524..9801c9b6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/PlayerAlbumCoverFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/PlayerAlbumCoverFragment.kt @@ -8,15 +8,13 @@ import androidx.viewpager.widget.ViewPager import code.name.monkey.retromusic.R import code.name.monkey.retromusic.adapter.album.AlbumCoverPagerAdapter import code.name.monkey.retromusic.adapter.album.AlbumCoverPagerAdapter.AlbumCoverFragment -import code.name.monkey.retromusic.fragments.NowPlayingScreen.ADAPTIVE -import code.name.monkey.retromusic.fragments.NowPlayingScreen.FIT -import code.name.monkey.retromusic.fragments.NowPlayingScreen.FULL +import code.name.monkey.retromusic.fragments.NowPlayingScreen.* import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.transform.CarousalPagerTransformer import code.name.monkey.retromusic.transform.ParallaxPagerTransformer import code.name.monkey.retromusic.util.PreferenceUtil -import kotlinx.android.synthetic.main.fragment_player_album_cover.viewPager +import kotlinx.android.synthetic.main.fragment_player_album_cover.* class PlayerAlbumCoverFragment : AbsMusicServiceFragment(), ViewPager.OnPageChangeListener { private var callbacks: Callbacks? = null @@ -56,7 +54,10 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(), ViewPager.OnPageChan viewPager.setPageTransformer(false, CarousalPagerTransformer(requireContext())) } else { viewPager.offscreenPageLimit = 2 - viewPager.setPageTransformer(true, PreferenceUtil.getInstance(requireContext()).albumCoverTransform) + viewPager.setPageTransformer( + true, + PreferenceUtil.getInstance(requireContext()).albumCoverTransform + ) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptiveFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptiveFragment.kt index ffa7e448..c8f4b13d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptiveFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptiveFragment.kt @@ -19,7 +19,7 @@ import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics import code.name.monkey.retromusic.model.lyrics.Lyrics -import kotlinx.android.synthetic.main.fragment_adaptive_player.playerToolbar +import kotlinx.android.synthetic.main.fragment_adaptive_player.* class AdaptiveFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Callback { @@ -55,7 +55,10 @@ class AdaptiveFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Call lyricsLine2.visibility = View.VISIBLE lyricsLine2.measure( - View.MeasureSpec.makeMeasureSpec(lyricsLine2.measuredWidth, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec( + lyricsLine2.measuredWidth, + View.MeasureSpec.EXACTLY + ), View.MeasureSpec.UNSPECIFIED ) val h: Float = lyricsLine2.measuredHeight.toFloat() @@ -79,12 +82,13 @@ class AdaptiveFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Call } private fun hideLyricsLayout() { - lyricsLayout.animate().alpha(0f).setDuration(VISIBILITY_ANIM_DURATION).withEndAction(Runnable { - if (!isLyricsLayoutBound()) return@Runnable - lyricsLayout.visibility = View.GONE - lyricsLine1.text = null - lyricsLine2.text = null - }) + lyricsLayout.animate().alpha(0f).setDuration(VISIBILITY_ANIM_DURATION) + .withEndAction(Runnable { + if (!isLyricsLayoutBound()) return@Runnable + lyricsLayout.visibility = View.GONE + lyricsLine1.text = null + lyricsLine2.text = null + }) } override fun setLyrics(l: Lyrics?) { @@ -116,7 +120,11 @@ class AdaptiveFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Call private var lastColor: Int = 0 private lateinit var playbackControlsFragment: AdaptivePlaybackControlsFragment - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_adaptive_player, container, false) } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt index bd8b2d93..90bf493c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt @@ -23,15 +23,7 @@ import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.ViewUtil -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.nextButton -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.playPauseButton -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.previousButton -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.progressSlider -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.repeatButton -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.shuffleButton -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.songCurrentProgress -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.songInfo -import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.songTotalTime +import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.* class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() { @@ -48,7 +40,11 @@ class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - return inflater.inflate(R.layout.fragment_adaptive_player_playback_controls, container, false) + return inflater.inflate( + R.layout.fragment_adaptive_player_playback_controls, + container, + false + ) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -109,12 +105,20 @@ class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() { } override fun setDark(color: Int) { - if (ColorUtil.isColorLight(ATHUtil.resolveColor(context, android.R.attr.windowBackground))) { + if (ColorUtil.isColorLight( + ATHUtil.resolveColor( + context, + android.R.attr.windowBackground + ) + ) + ) { lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true) - lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true) + lastDisabledPlaybackControlsColor = + MaterialValueHelper.getSecondaryDisabledTextColor(activity, true) } else { lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false) - lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false) + lastDisabledPlaybackControlsColor = + MaterialValueHelper.getPrimaryDisabledTextColor(activity, false) } updateRepeatState() @@ -183,7 +187,10 @@ class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> shuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -195,7 +202,10 @@ class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + repeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt index cb466d23..085e60ec 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt @@ -23,17 +23,7 @@ import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.PreferenceUtil -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.nextButton -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.playPauseButton -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.previousButton -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.progressSlider -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.repeatButton -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.shuffleButton -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.songCurrentProgress -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.songInfo -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.songTotalTime -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.text -import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.title +import kotlinx.android.synthetic.main.fragment_blur_player_playback_controls.* class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() { @@ -119,7 +109,8 @@ class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() { override fun setDark(color: Int) { lastPlaybackControlsColor = Color.WHITE - lastDisabledPlaybackControlsColor = ContextCompat.getColor(requireContext(), R.color.md_grey_500) + lastDisabledPlaybackControlsColor = + ContextCompat.getColor(requireContext(), R.color.md_grey_500) title.setTextColor(lastPlaybackControlsColor) @@ -188,7 +179,10 @@ class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> shuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -200,7 +194,10 @@ class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + repeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlayerFragment.kt index 570e6805..6c5002b5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlayerFragment.kt @@ -19,8 +19,7 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.util.PreferenceUtil import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.fragment_blur.colorBackground -import kotlinx.android.synthetic.main.fragment_blur.playerToolbar +import kotlinx.android.synthetic.main.fragment_blur.* class BlurPlayerFragment : AbsPlayerFragment(), SharedPreferences.OnSharedPreferenceChangeListener { @@ -126,7 +125,8 @@ class BlurPlayerFragment : AbsPlayerFragment(), SharedPreferences.OnSharedPrefer override fun onResume() { super.onResume() - PreferenceManager.getDefaultSharedPreferences(requireContext()).registerOnSharedPreferenceChangeListener(this) + PreferenceManager.getDefaultSharedPreferences(requireContext()) + .registerOnSharedPreferenceChangeListener(this) } override fun onDestroyView() { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardFragment.kt index 91f9cea7..d347f81b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardFragment.kt @@ -13,7 +13,7 @@ import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Song -import kotlinx.android.synthetic.main.fragment_card_player.playerToolbar +import kotlinx.android.synthetic.main.fragment_card_player.* class CardFragment : AbsPlayerFragment() { override fun playerToolbar(): Toolbar { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardPlaybackControlsFragment.kt index e04de9fa..e2bdf4cd 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardPlaybackControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/card/CardPlaybackControlsFragment.kt @@ -25,18 +25,8 @@ import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.PreferenceUtil -import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.image -import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.progressSlider -import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.songCurrentProgress -import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.songInfo -import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.songTotalTime -import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.text -import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.title -import kotlinx.android.synthetic.main.media_button.nextButton -import kotlinx.android.synthetic.main.media_button.playPauseButton -import kotlinx.android.synthetic.main.media_button.previousButton -import kotlinx.android.synthetic.main.media_button.repeatButton -import kotlinx.android.synthetic.main.media_button.shuffleButton +import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.* +import kotlinx.android.synthetic.main.media_button.* class CardPlaybackControlsFragment : AbsPlayerControlsFragment() { @@ -121,12 +111,20 @@ class CardPlaybackControlsFragment : AbsPlayerControlsFragment() { override fun setDark(color: Int) { - if (ColorUtil.isColorLight(ATHUtil.resolveColor(context, android.R.attr.windowBackground))) { + if (ColorUtil.isColorLight( + ATHUtil.resolveColor( + context, + android.R.attr.windowBackground + ) + ) + ) { lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true) - lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true) + lastDisabledPlaybackControlsColor = + MaterialValueHelper.getSecondaryDisabledTextColor(activity, true) } else { lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false) - lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false) + lastDisabledPlaybackControlsColor = + MaterialValueHelper.getPrimaryDisabledTextColor(activity, false) } updateRepeatState() @@ -196,7 +194,10 @@ class CardPlaybackControlsFragment : AbsPlayerControlsFragment() { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> shuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -208,7 +209,10 @@ class CardPlaybackControlsFragment : AbsPlayerControlsFragment() { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + repeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) @@ -252,7 +256,10 @@ class CardPlaybackControlsFragment : AbsPlayerControlsFragment() { override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { if (fromUser) { MusicPlayerRemote.seekTo(progress) - onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis) + onUpdateProgressViews( + MusicPlayerRemote.songProgressMillis, + MusicPlayerRemote.songDurationMillis + ) } } }) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurFragment.kt index f1854004..05ce400c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurFragment.kt @@ -20,8 +20,7 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.util.PreferenceUtil import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.fragment_card_blur_player.colorBackground -import kotlinx.android.synthetic.main.fragment_card_blur_player.playerToolbar +import kotlinx.android.synthetic.main.fragment_card_blur_player.* class CardBlurFragment : AbsPlayerFragment(), SharedPreferences.OnSharedPreferenceChangeListener { override fun playerToolbar(): Toolbar { @@ -146,7 +145,8 @@ class CardBlurFragment : AbsPlayerFragment(), SharedPreferences.OnSharedPreferen override fun onResume() { super.onResume() - PreferenceManager.getDefaultSharedPreferences(requireContext()).registerOnSharedPreferenceChangeListener(this) + PreferenceManager.getDefaultSharedPreferences(requireContext()) + .registerOnSharedPreferenceChangeListener(this) } override fun onDestroyView() { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt index 7326d247..a6463964 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt @@ -22,15 +22,8 @@ import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.ViewUtil -import kotlinx.android.synthetic.main.fragment_card_blur_player_playback_controls.progressSlider -import kotlinx.android.synthetic.main.fragment_card_blur_player_playback_controls.songCurrentProgress -import kotlinx.android.synthetic.main.fragment_card_blur_player_playback_controls.songInfo -import kotlinx.android.synthetic.main.fragment_card_blur_player_playback_controls.songTotalTime -import kotlinx.android.synthetic.main.media_button.nextButton -import kotlinx.android.synthetic.main.media_button.playPauseButton -import kotlinx.android.synthetic.main.media_button.previousButton -import kotlinx.android.synthetic.main.media_button.repeatButton -import kotlinx.android.synthetic.main.media_button.shuffleButton +import kotlinx.android.synthetic.main.fragment_card_blur_player_playback_controls.* +import kotlinx.android.synthetic.main.media_button.* class CardBlurPlaybackControlsFragment : AbsPlayerControlsFragment() { @@ -48,7 +41,11 @@ class CardBlurPlaybackControlsFragment : AbsPlayerControlsFragment() { savedInstanceState: Bundle? ): View? { - return inflater.inflate(R.layout.fragment_card_blur_player_playback_controls, container, false) + return inflater.inflate( + R.layout.fragment_card_blur_player_playback_controls, + container, + false + ) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -163,7 +160,10 @@ class CardBlurPlaybackControlsFragment : AbsPlayerControlsFragment() { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> shuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -175,7 +175,10 @@ class CardBlurPlaybackControlsFragment : AbsPlayerControlsFragment() { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + repeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt index dea50e38..75053811 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt @@ -43,23 +43,14 @@ import code.name.monkey.retromusic.views.SeekArc import code.name.monkey.retromusic.views.SeekArc.OnSeekArcChangeListener import code.name.monkey.retromusic.volume.AudioVolumeObserver import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener -import kotlinx.android.synthetic.main.fragment_circle_player.nextButton -import kotlinx.android.synthetic.main.fragment_circle_player.playPauseButton -import kotlinx.android.synthetic.main.fragment_circle_player.playerToolbar -import kotlinx.android.synthetic.main.fragment_circle_player.previousButton -import kotlinx.android.synthetic.main.fragment_circle_player.progressSlider -import kotlinx.android.synthetic.main.fragment_circle_player.songCurrentProgress -import kotlinx.android.synthetic.main.fragment_circle_player.songInfo -import kotlinx.android.synthetic.main.fragment_circle_player.songTotalTime -import kotlinx.android.synthetic.main.fragment_circle_player.text -import kotlinx.android.synthetic.main.fragment_circle_player.title -import kotlinx.android.synthetic.main.fragment_circle_player.volumeSeekBar +import kotlinx.android.synthetic.main.fragment_circle_player.* /** * Created by hemanths on 2020-01-06. */ -class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChangedListener, OnSeekArcChangeListener { +class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChangedListener, + OnSeekArcChangeListener { private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper private var audioVolumeObserver: AudioVolumeObserver? = null @@ -72,7 +63,11 @@ class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChanged progressViewUpdateHelper = MusicProgressViewUpdateHelper(this) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_circle_player, container, false) } @@ -97,7 +92,11 @@ class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChanged private fun setupViews() { setUpProgressSlider() - ViewUtil.setProgressDrawable(progressSlider, ThemeStore.accentColor(requireContext())) + ViewUtil.setProgressDrawable( + progressSlider, + ThemeStore.accentColor(requireContext()), + false + ) volumeSeekBar.progressColor = ThemeStore.accentColor(requireContext()) setUpPlayPauseFab() setUpPrevNext() @@ -155,7 +154,8 @@ class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChanged override fun onBackPressed(): Boolean = false - override fun toolbarIconColor(): Int = ATHUtil.resolveColor(requireContext(), android.R.attr.colorControlNormal) + override fun toolbarIconColor(): Int = + ATHUtil.resolveColor(requireContext(), android.R.attr.colorControlNormal) override val paletteColor: Int get() = Color.BLACK diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorFragment.kt index 547e898d..ec36604d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorFragment.kt @@ -22,9 +22,7 @@ import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.RetroColorUtil import com.bumptech.glide.Glide import com.bumptech.glide.request.animation.GlideAnimation -import kotlinx.android.synthetic.main.fragment_color_player.colorGradientBackground -import kotlinx.android.synthetic.main.fragment_color_player.playerImage -import kotlinx.android.synthetic.main.fragment_color_player.playerToolbar +import kotlinx.android.synthetic.main.fragment_color_player.* class ColorFragment : AbsPlayerFragment() { @@ -80,7 +78,11 @@ class ColorFragment : AbsPlayerFragment() { } } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_color_player, container, false) } @@ -94,7 +96,8 @@ class ColorFragment : AbsPlayerFragment() { } private fun setUpSubFragments() { - playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as ColorPlaybackControlsFragment + playbackControlsFragment = + childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as ColorPlaybackControlsFragment } private fun setUpPlayerToolbar() { @@ -102,7 +105,11 @@ class ColorFragment : AbsPlayerFragment() { inflateMenu(R.menu.menu_player) setNavigationOnClickListener { requireActivity().onBackPressed() } setOnMenuItemClickListener(this@ColorFragment) - ToolbarContentTintHelper.colorizeToolbar(this, ATHUtil.resolveColor(requireContext(), R.attr.colorControlNormal), requireActivity()) + ToolbarContentTintHelper.colorizeToolbar( + this, + ATHUtil.resolveColor(requireContext(), R.attr.colorControlNormal), + requireActivity() + ) } } @@ -118,39 +125,43 @@ class ColorFragment : AbsPlayerFragment() { private fun updateSong() { Builder.from(Glide.with(requireActivity()), MusicPlayerRemote.currentSong) - .checkIgnoreMediaStore(requireContext()) - .generatePalette(requireContext()) - .build() - .into(object : RetroMusicColoredTarget(playerImage) { - override fun onColorReady(color: Int) { + .checkIgnoreMediaStore(requireContext()) + .generatePalette(requireContext()) + .build() + .into(object : RetroMusicColoredTarget(playerImage) { + override fun onColorReady(color: Int) { - } + } - override fun onResourceReady( - resource: BitmapPaletteWrapper?, - glideAnimation: GlideAnimation? - ) { - super.onResourceReady(resource, glideAnimation) - resource?.let { - val palette = resource.palette - val swatch = RetroColorUtil.getSwatch(palette) + override fun onResourceReady( + resource: BitmapPaletteWrapper?, + glideAnimation: GlideAnimation? + ) { + super.onResourceReady(resource, glideAnimation) + resource?.let { + val palette = resource.palette + val swatch = RetroColorUtil.getSwatch(palette) - val textColor = RetroColorUtil.getTextColor(palette) - val backgroundColor = swatch.rgb + val textColor = RetroColorUtil.getTextColor(palette) + val backgroundColor = swatch.rgb - setColors(backgroundColor, textColor) - } - - } - - override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { - super.onLoadFailed(e, errorDrawable) - val backgroundColor = defaultFooterColor - val textColor = if (ColorUtil.isColorLight(defaultFooterColor)) MaterialValueHelper.getPrimaryTextColor(requireContext(), true) - else MaterialValueHelper.getPrimaryTextColor(requireContext(), false) setColors(backgroundColor, textColor) } - }) + + } + + override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { + super.onLoadFailed(e, errorDrawable) + val backgroundColor = defaultFooterColor + val textColor = + if (ColorUtil.isColorLight(defaultFooterColor)) MaterialValueHelper.getPrimaryTextColor( + requireContext(), + true + ) + else MaterialValueHelper.getPrimaryTextColor(requireContext(), false) + setColors(backgroundColor, textColor) + } + }) } private fun setColors(backgroundColor: Int, componentsColor: Int) { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitFragment.kt index 64bf03b6..44461b37 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitFragment.kt @@ -12,7 +12,7 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Song -import kotlinx.android.synthetic.main.fragment_fit.playerToolbar +import kotlinx.android.synthetic.main.fragment_fit.* class FitFragment : AbsPlayerFragment() { override fun playerToolbar(): Toolbar { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlayerFragment.kt index 8c3155fb..ed558b3a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlayerFragment.kt @@ -20,8 +20,7 @@ import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.ViewUtil import code.name.monkey.retromusic.views.DrawableGradient -import kotlinx.android.synthetic.main.fragment_flat_player.colorGradientBackground -import kotlinx.android.synthetic.main.fragment_flat_player.playerToolbar +import kotlinx.android.synthetic.main.fragment_flat_player.* class FlatPlayerFragment : AbsPlayerFragment() { override fun playerToolbar(): Toolbar { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlayerFragment.kt index e8bab308..2af78fe8 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlayerFragment.kt @@ -25,10 +25,7 @@ import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics import code.name.monkey.retromusic.model.lyrics.Lyrics import code.name.monkey.retromusic.util.NavigationUtil import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.fragment_full.artistImage -import kotlinx.android.synthetic.main.fragment_full.nextSong -import kotlinx.android.synthetic.main.fragment_full.nextSongLabel -import kotlinx.android.synthetic.main.fragment_full.playerToolbar +import kotlinx.android.synthetic.main.fragment_full.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -67,7 +64,10 @@ class FullPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca lyricsLine2.visibility = View.VISIBLE lyricsLine2.measure( - View.MeasureSpec.makeMeasureSpec(lyricsLine2.measuredWidth, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec( + lyricsLine2.measuredWidth, + View.MeasureSpec.EXACTLY + ), View.MeasureSpec.UNSPECIFIED ) val h: Float = lyricsLine2.measuredHeight.toFloat() @@ -91,12 +91,13 @@ class FullPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca } private fun hideLyricsLayout() { - lyricsLayout.animate().alpha(0f).setDuration(VISIBILITY_ANIM_DURATION).withEndAction(Runnable { - if (!isLyricsLayoutBound()) return@Runnable - lyricsLayout.visibility = View.GONE - lyricsLine1.text = null - lyricsLine2.text = null - }) + lyricsLayout.animate().alpha(0f).setDuration(VISIBILITY_ANIM_DURATION) + .withEndAction(Runnable { + if (!isLyricsLayoutBound()) return@Runnable + lyricsLayout.visibility = View.GONE + lyricsLine1.text = null + lyricsLine2.text = null + }) } override fun setLyrics(l: Lyrics?) { @@ -158,7 +159,11 @@ class FullPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca val transitionName = "${getString(R.string.transition_artist_image)}_${MusicPlayerRemote.currentSong.artistId}" val activityOptions = - ActivityOptions.makeSceneTransitionAnimation(requireActivity(), artistImage, transitionName) + ActivityOptions.makeSceneTransitionAnimation( + requireActivity(), + artistImage, + transitionName + ) NavigationUtil.goToArtistOptions( requireActivity(), MusicPlayerRemote.currentSong.artistId, @@ -229,7 +234,8 @@ class FullPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca private fun updateArtistImage() { CoroutineScope(Dispatchers.IO).launch { - val artist = ArtistLoader.getArtist(requireContext(), MusicPlayerRemote.currentSong.artistId) + val artist = + ArtistLoader.getArtist(requireContext(), MusicPlayerRemote.currentSong.artistId) withContext(Dispatchers.Main) { ArtistGlideRequest.Builder.from(Glide.with(requireContext()), artist) .generatePalette(requireContext()) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/lockscreen/LockScreenPlayerControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/lockscreen/LockScreenPlayerControlsFragment.kt index 2eb8797b..b0c8672d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/lockscreen/LockScreenPlayerControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/lockscreen/LockScreenPlayerControlsFragment.kt @@ -39,16 +39,7 @@ import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.ViewUtil -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.nextButton -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.playPauseButton -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.previousButton -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.progressSlider -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.repeatButton -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.shuffleButton -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.songCurrentProgress -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.songTotalTime -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.text -import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.title +import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.* /** * @author Hemanth S (h4h13). @@ -122,11 +113,13 @@ class LockScreenPlayerControlsFragment : AbsPlayerControlsFragment() { val colorBg = ATHUtil.resolveColor(requireContext(), android.R.attr.colorBackground) if (ColorUtil.isColorLight(colorBg)) { - lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(requireContext(), true) + lastPlaybackControlsColor = + MaterialValueHelper.getSecondaryTextColor(requireContext(), true) lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(requireContext(), true) } else { - lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(requireContext(), false) + lastPlaybackControlsColor = + MaterialValueHelper.getPrimaryTextColor(requireContext(), false) lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(requireContext(), false) } @@ -194,7 +187,10 @@ class LockScreenPlayerControlsFragment : AbsPlayerControlsFragment() { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> shuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -206,7 +202,10 @@ class LockScreenPlayerControlsFragment : AbsPlayerControlsFragment() { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + repeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialFragment.kt index eb4f5834..3b40917f 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialFragment.kt @@ -13,7 +13,7 @@ import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Song -import kotlinx.android.synthetic.main.fragment_material.playerToolbar +import kotlinx.android.synthetic.main.fragment_material.* /** * @author Hemanth S (h4h13). diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerFragment.kt index f31e4883..db186aa5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerFragment.kt @@ -36,12 +36,20 @@ class PlayerFragment : AbsPlayerFragment() { valueAnimator?.cancel() } - valueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), ATHUtil.resolveColor(requireContext(), R.attr.colorSurface), i) + valueAnimator = ValueAnimator.ofObject( + ArgbEvaluator(), + ATHUtil.resolveColor(requireContext(), R.attr.colorSurface), + i + ) valueAnimator?.addUpdateListener { animation -> if (isAdded) { - val drawable = DrawableGradient(GradientDrawable.Orientation.TOP_BOTTOM, - intArrayOf(animation.animatedValue as Int, - ATHUtil.resolveColor(requireContext(), R.attr.colorSurface)), 0) + val drawable = DrawableGradient( + GradientDrawable.Orientation.TOP_BOTTOM, + intArrayOf( + animation.animatedValue as Int, + ATHUtil.resolveColor(requireContext(), R.attr.colorSurface) + ), 0 + ) colorGradientBackground?.background = drawable } } @@ -70,7 +78,11 @@ class PlayerFragment : AbsPlayerFragment() { lastColor = color callbacks?.onPaletteColorChanged() - ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.colorControlNormal), requireActivity()) + ToolbarContentTintHelper.colorizeToolbar( + playerToolbar, + ATHUtil.resolveColor(context, R.attr.colorControlNormal), + requireActivity() + ) if (PreferenceUtil.getInstance(requireContext()).adaptiveColor) { colorize(color) @@ -89,8 +101,10 @@ class PlayerFragment : AbsPlayerFragment() { } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_player, container, false) } @@ -103,17 +117,23 @@ class PlayerFragment : AbsPlayerFragment() { private fun setUpSubFragments() { - playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as PlayerPlaybackControlsFragment - val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment + playbackControlsFragment = + childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as PlayerPlaybackControlsFragment + val playerAlbumCoverFragment = + childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment playerAlbumCoverFragment.setCallbacks(this) } private fun setUpPlayerToolbar() { playerToolbar.inflateMenu(R.menu.menu_player) - playerToolbar.setNavigationOnClickListener {requireActivity().onBackPressed() } + playerToolbar.setNavigationOnClickListener { requireActivity().onBackPressed() } playerToolbar.setOnMenuItemClickListener(this) - ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.colorControlNormal), requireActivity()) + ToolbarContentTintHelper.colorizeToolbar( + playerToolbar, + ATHUtil.resolveColor(context, R.attr.colorControlNormal), + requireActivity() + ) } override fun onServiceConnected() { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerFragment.kt index 6b454ebb..4e9a9391 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerFragment.kt @@ -31,11 +31,7 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.PreferenceUtil import com.bumptech.glide.Glide -import kotlinx.android.synthetic.main.fragment_peak_player.playerImage -import kotlinx.android.synthetic.main.fragment_peak_player.playerToolbar -import kotlinx.android.synthetic.main.fragment_peak_player.songInfo -import kotlinx.android.synthetic.main.fragment_peak_player.text -import kotlinx.android.synthetic.main.fragment_peak_player.title +import kotlinx.android.synthetic.main.fragment_peak_player.* /** * Created by hemanths on 2019-10-03. @@ -46,7 +42,11 @@ class PeakPlayerFragment : AbsPlayerFragment() { private lateinit var playbackControlsFragment: PeakPlayerControlFragment private var lastColor: Int = 0 - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_peak_player, container, false) } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlayerFragment.kt index 30241f14..d609f7d6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlayerFragment.kt @@ -12,9 +12,7 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Song -import kotlinx.android.synthetic.main.fragment_plain_player.playerToolbar -import kotlinx.android.synthetic.main.fragment_plain_player.text -import kotlinx.android.synthetic.main.fragment_plain_player.title +import kotlinx.android.synthetic.main.fragment_plain_player.* class PlainPlayerFragment : AbsPlayerFragment() { override fun playerToolbar(): Toolbar { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlaybackControlsFragment.kt index 1d2da9ba..39539e31 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlaybackControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlaybackControlsFragment.kt @@ -21,15 +21,7 @@ import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.PreferenceUtil -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.nextButton -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.playPauseButton -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.previousButton -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.repeatButton -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.shuffleButton -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.songCurrentProgress -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.songInfo -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.text -import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.title +import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.* /** * @author Hemanth S (h4h13). @@ -65,7 +57,11 @@ class SimplePlaybackControlsFragment : AbsPlayerControlsFragment() { progressViewUpdateHelper = MusicProgressViewUpdateHelper(this) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_simple_controls_fragment, container, false) } @@ -122,7 +118,10 @@ class SimplePlaybackControlsFragment : AbsPlayerControlsFragment() { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> shuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -134,7 +133,10 @@ class SimplePlaybackControlsFragment : AbsPlayerControlsFragment() { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + repeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) @@ -199,10 +201,12 @@ class SimplePlaybackControlsFragment : AbsPlayerControlsFragment() { val colorBg = ATHUtil.resolveColor(context!!, android.R.attr.colorBackground) if (ColorUtil.isColorLight(colorBg)) { lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context!!, true) - lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true) + lastDisabledPlaybackControlsColor = + MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true) } else { lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context!!, false) - lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false) + lastDisabledPlaybackControlsColor = + MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false) } val colorFinal = if (PreferenceUtil.getInstance(requireContext()).adaptiveColor) { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlayerFragment.kt index 4b08839f..525b5f81 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/simple/SimplePlayerFragment.kt @@ -12,7 +12,7 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.Song -import kotlinx.android.synthetic.main.fragment_simple_player.playerToolbar +import kotlinx.android.synthetic.main.fragment_simple_player.* /** * @author Hemanth S (h4h13). diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlaybackControlsFragment.kt index 686f556e..070f0429 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlaybackControlsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlaybackControlsFragment.kt @@ -11,8 +11,7 @@ import code.name.monkey.retromusic.R import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.service.MusicService -import kotlinx.android.synthetic.main.fragment_tiny_controls_fragment.playerRepeatButton -import kotlinx.android.synthetic.main.fragment_tiny_controls_fragment.playerShuffleButton +import kotlinx.android.synthetic.main.fragment_tiny_controls_fragment.* class TinyPlaybackControlsFragment : AbsPlayerControlsFragment() { @@ -28,11 +27,13 @@ class TinyPlaybackControlsFragment : AbsPlayerControlsFragment() { override fun setDark(color: Int) { if (ColorUtil.isColorLight(color)) { - lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(requireContext(), true) + lastPlaybackControlsColor = + MaterialValueHelper.getSecondaryTextColor(requireContext(), true) lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(requireContext(), true) } else { - lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(requireContext(), false) + lastPlaybackControlsColor = + MaterialValueHelper.getPrimaryTextColor(requireContext(), false) lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(requireContext(), false) } @@ -47,7 +48,11 @@ class TinyPlaybackControlsFragment : AbsPlayerControlsFragment() { private var lastPlaybackControlsColor: Int = 0 private var lastDisabledPlaybackControlsColor: Int = 0 - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_tiny_controls_fragment, container, false) } @@ -76,7 +81,10 @@ class TinyPlaybackControlsFragment : AbsPlayerControlsFragment() { lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN ) - else -> playerShuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + else -> playerShuffleButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } } @@ -84,7 +92,10 @@ class TinyPlaybackControlsFragment : AbsPlayerControlsFragment() { when (MusicPlayerRemote.repeatMode) { MusicService.REPEAT_MODE_NONE -> { playerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) - playerRepeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN) + playerRepeatButton.setColorFilter( + lastDisabledPlaybackControlsColor, + PorterDuff.Mode.SRC_IN + ) } MusicService.REPEAT_MODE_ALL -> { playerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AbsSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AbsSettingsFragment.kt index 97b96baa..225f936f 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AbsSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AbsSettingsFragment.kt @@ -26,16 +26,7 @@ import androidx.preference.PreferenceManager import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.retromusic.R -import code.name.monkey.retromusic.preferences.AlbumCoverStylePreference -import code.name.monkey.retromusic.preferences.AlbumCoverStylePreferenceDialog -import code.name.monkey.retromusic.preferences.BlacklistPreference -import code.name.monkey.retromusic.preferences.BlacklistPreferenceDialog -import code.name.monkey.retromusic.preferences.LibraryPreference -import code.name.monkey.retromusic.preferences.LibraryPreferenceDialog -import code.name.monkey.retromusic.preferences.MaterialListPreference -import code.name.monkey.retromusic.preferences.MaterialListPreferenceDialog -import code.name.monkey.retromusic.preferences.NowPlayingScreenPreference -import code.name.monkey.retromusic.preferences.NowPlayingScreenPreferenceDialog +import code.name.monkey.retromusic.preferences.* import code.name.monkey.retromusic.util.NavigationUtil /** @@ -45,7 +36,8 @@ import code.name.monkey.retromusic.util.NavigationUtil abstract class AbsSettingsFragment : ATEPreferenceFragmentCompat() { internal fun showProToastAndNavigate(message: String) { - Toast.makeText(requireContext(), "$message is Pro version feature.", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "$message is Pro version feature.", Toast.LENGTH_SHORT) + .show() NavigationUtil.goToProVersion(requireActivity()) } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/MainSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/MainSettingsFragment.kt index b2c10eb8..2a690c08 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/MainSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/MainSettingsFragment.kt @@ -28,27 +28,32 @@ import code.name.monkey.retromusic.activities.SettingsActivity import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.util.NavigationUtil -import kotlinx.android.synthetic.main.fragment_main_settings.aboutSettings -import kotlinx.android.synthetic.main.fragment_main_settings.audioSettings -import kotlinx.android.synthetic.main.fragment_main_settings.buyPremium -import kotlinx.android.synthetic.main.fragment_main_settings.buyProContainer -import kotlinx.android.synthetic.main.fragment_main_settings.diamondIcon -import kotlinx.android.synthetic.main.fragment_main_settings.generalSettings -import kotlinx.android.synthetic.main.fragment_main_settings.imageSettings -import kotlinx.android.synthetic.main.fragment_main_settings.notificationSettings -import kotlinx.android.synthetic.main.fragment_main_settings.nowPlayingSettings -import kotlinx.android.synthetic.main.fragment_main_settings.otherSettings -import kotlinx.android.synthetic.main.fragment_main_settings.personalizeSettings +import kotlinx.android.synthetic.main.fragment_main_settings.* class MainSettingsFragment : Fragment(), View.OnClickListener { override fun onClick(view: View) { when (view.id) { - R.id.generalSettings -> inflateFragment(ThemeSettingsFragment(), R.string.general_settings_title) + R.id.generalSettings -> inflateFragment( + ThemeSettingsFragment(), + R.string.general_settings_title + ) R.id.audioSettings -> inflateFragment(AudioSettings(), R.string.pref_header_audio) - R.id.nowPlayingSettings -> inflateFragment(NowPlayingSettingsFragment(), R.string.now_playing) - R.id.personalizeSettings -> inflateFragment(PersonalizeSettingsFragment(), R.string.personalize) - R.id.imageSettings -> inflateFragment(ImageSettingFragment(), R.string.pref_header_images) - R.id.notificationSettings -> inflateFragment(NotificationSettingsFragment(), R.string.notification) + R.id.nowPlayingSettings -> inflateFragment( + NowPlayingSettingsFragment(), + R.string.now_playing + ) + R.id.personalizeSettings -> inflateFragment( + PersonalizeSettingsFragment(), + R.string.personalize + ) + R.id.imageSettings -> inflateFragment( + ImageSettingFragment(), + R.string.pref_header_images + ) + R.id.notificationSettings -> inflateFragment( + NotificationSettingsFragment(), + R.string.notification + ) R.id.otherSettings -> inflateFragment(OtherSettingsFragment(), R.string.others) R.id.aboutSettings -> NavigationUtil.goToAbout(requireActivity()) } @@ -88,6 +93,10 @@ class MainSettingsFragment : Fragment(), View.OnClickListener { } } + companion object { + + } + private fun inflateFragment(fragment: Fragment, @StringRes title: Int) { (requireActivity() as SettingsActivity).setupFragment(fragment, title) } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NotificationSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NotificationSettingsFragment.kt index dfd74f15..63458bbc 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NotificationSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NotificationSettingsFragment.kt @@ -28,11 +28,13 @@ import code.name.monkey.retromusic.util.PreferenceUtil * @author Hemanth S (h4h13). */ -class NotificationSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnSharedPreferenceChangeListener { +class NotificationSettingsFragment : AbsSettingsFragment(), + SharedPreferences.OnSharedPreferenceChangeListener { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { if (key == PreferenceUtil.CLASSIC_NOTIFICATION) { if (VERSION.SDK_INT >= VERSION_CODES.O) { - findPreference("colored_notification")?.isEnabled = sharedPreferences?.getBoolean(key, false)!! + findPreference("colored_notification")?.isEnabled = + sharedPreferences?.getBoolean(key, false)!! } } } @@ -47,7 +49,8 @@ class NotificationSettingsFragment : AbsSettingsFragment(), SharedPreferences.On isChecked = PreferenceUtil.getInstance(requireContext()).classicNotification() setOnPreferenceChangeListener { _, newValue -> // Save preference - PreferenceUtil.getInstance(requireContext()).setClassicNotification(newValue as Boolean) + PreferenceUtil.getInstance(requireContext()) + .setClassicNotification(newValue as Boolean) invalidateSettings() true } @@ -56,12 +59,14 @@ class NotificationSettingsFragment : AbsSettingsFragment(), SharedPreferences.On val coloredNotification: TwoStatePreference? = findPreference("colored_notification") if (VERSION.SDK_INT >= VERSION_CODES.O) { - coloredNotification?.isEnabled = PreferenceUtil.getInstance(requireContext()).classicNotification() + coloredNotification?.isEnabled = + PreferenceUtil.getInstance(requireContext()).classicNotification() } else { coloredNotification?.apply { isChecked = PreferenceUtil.getInstance(requireContext()).coloredNotification() setOnPreferenceChangeListener { _, newValue -> - PreferenceUtil.getInstance(requireContext()).setColoredNotification(newValue as Boolean) + PreferenceUtil.getInstance(requireContext()) + .setColoredNotification(newValue as Boolean) true } } @@ -75,7 +80,8 @@ class NotificationSettingsFragment : AbsSettingsFragment(), SharedPreferences.On override fun onDestroyView() { super.onDestroyView() - PreferenceUtil.getInstance(requireContext()).unregisterOnSharedPreferenceChangedListener(this) + PreferenceUtil.getInstance(requireContext()) + .unregisterOnSharedPreferenceChangedListener(this) } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NowPlayingSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NowPlayingSettingsFragment.kt index b596729b..ffccd739 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NowPlayingSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/NowPlayingSettingsFragment.kt @@ -27,7 +27,8 @@ import code.name.monkey.retromusic.util.PreferenceUtil.* * @author Hemanth S (h4h13). */ -class NowPlayingSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnSharedPreferenceChangeListener { +class NowPlayingSettingsFragment : AbsSettingsFragment(), + SharedPreferences.OnSharedPreferenceChangeListener { override fun invalidateSettings() { updateNowPlayingScreenSummary() diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt index fd49bdb2..6877c714 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt @@ -22,7 +22,8 @@ import androidx.preference.TwoStatePreference import code.name.monkey.retromusic.R import code.name.monkey.retromusic.util.PreferenceUtil -class PersonalizeSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnSharedPreferenceChangeListener { +class PersonalizeSettingsFragment : AbsSettingsFragment(), + SharedPreferences.OnSharedPreferenceChangeListener { override fun invalidateSettings() { @@ -49,7 +50,8 @@ class PersonalizeSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnS override fun onDestroyView() { super.onDestroyView() - PreferenceUtil.getInstance(requireContext()).unregisterOnSharedPreferenceChangedListener(this) + PreferenceUtil.getInstance(requireContext()) + .unregisterOnSharedPreferenceChangedListener(this) } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt index c5ce30e6..55855880 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt @@ -67,7 +67,11 @@ class ThemeSettingsFragment : AbsSettingsFragment() { cornerRadius(PreferenceUtil.getInstance(requireContext()).dialogCorner) title(R.string.accent_color) positiveButton(R.string.set) - colorChooser(colors = ACCENT_COLORS, allowCustomArgb = true, subColors = ACCENT_COLORS_SUB) { _, color -> + colorChooser( + colors = ACCENT_COLORS, + allowCustomArgb = true, + subColors = ACCENT_COLORS_SUB + ) { _, color -> ThemeStore.editTheme(requireContext()).accentColor(color).commit() if (VersionUtils.hasNougatMR()) DynamicShortcutManager(requireContext()).updateDynamicShortcuts() @@ -91,10 +95,12 @@ class ThemeSettingsFragment : AbsSettingsFragment() { true } - val desaturatedColor: ATESwitchPreference? = findPreference(PreferenceUtil.DESATURATED_COLOR) + val desaturatedColor: ATESwitchPreference? = + findPreference(PreferenceUtil.DESATURATED_COLOR) desaturatedColor?.setOnPreferenceChangeListener { _, value -> val desaturated = value as Boolean - ThemeStore.prefs(requireContext()).edit().putBoolean("desaturated_color", desaturated).apply() + ThemeStore.prefs(requireContext()).edit().putBoolean("desaturated_color", desaturated) + .apply() PreferenceUtil.getInstance(requireContext()).setDesaturatedColor(desaturated) requireActivity().recreate() true @@ -105,10 +111,12 @@ class ThemeSettingsFragment : AbsSettingsFragment() { if (!VersionUtils.hasNougatMR()) { colorAppShortcuts.isVisible = false } else { - colorAppShortcuts.isChecked = PreferenceUtil.getInstance(requireContext()).coloredAppShortcuts() + colorAppShortcuts.isChecked = + PreferenceUtil.getInstance(requireContext()).coloredAppShortcuts() colorAppShortcuts.setOnPreferenceChangeListener { _, newValue -> // Save preference - PreferenceUtil.getInstance(requireContext()).setColoredAppShortcuts(newValue as Boolean) + PreferenceUtil.getInstance(requireContext()) + .setColoredAppShortcuts(newValue as Boolean) DynamicShortcutManager(requireContext()).updateDynamicShortcuts() true } diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/AlbumGlideRequest.java b/app/src/main/java/code/name/monkey/retromusic/glide/AlbumGlideRequest.java index 41b2744a..aed589d3 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/AlbumGlideRequest.java +++ b/app/src/main/java/code/name/monkey/retromusic/glide/AlbumGlideRequest.java @@ -4,7 +4,6 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; @@ -17,8 +16,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.signature.MediaStoreSignature; -import code.name.monkey.appthemehelper.ThemeStore; -import code.name.monkey.appthemehelper.util.TintHelper; import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.glide.audiocover.AudioFileCover; import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder; @@ -32,21 +29,37 @@ public class AlbumGlideRequest { private static final int DEFAULT_ERROR_IMAGE = R.drawable.default_album_art; private static final int DEFAULT_ANIMATION = android.R.anim.fade_in; + @NonNull + private static DrawableTypeRequest createBaseRequest(@NonNull RequestManager requestManager, + @NonNull Song song, + boolean ignoreMediaStore) { + if (ignoreMediaStore) { + return requestManager.load(new AudioFileCover(song.getData())); + } else { + return requestManager.loadFromMediaStore(MusicUtil.getMediaStoreAlbumCoverUri(song.getAlbumId())); + } + } + + @NonNull + private static Key createSignature(@NonNull Song song) { + return new MediaStoreSignature("", song.getDateModified(), 0); + } + public static class Builder { final RequestManager requestManager; final Song song; boolean ignoreMediaStore; - @NonNull - public static Builder from(@NonNull RequestManager requestManager, Song song) { - return new Builder(requestManager, song); - } - private Builder(@NonNull RequestManager requestManager, Song song) { this.requestManager = requestManager; this.song = song; } + @NonNull + public static Builder from(@NonNull RequestManager requestManager, Song song) { + return new Builder(requestManager, song); + } + @NonNull public PaletteBuilder generatePalette(@NonNull Context context) { return new PaletteBuilder(this, context); @@ -98,6 +111,7 @@ public class AlbumGlideRequest { } public static class PaletteBuilder { + private static final String TAG = "PaletteBuilder"; final Context context; private final Builder builder; @@ -107,32 +121,15 @@ public class AlbumGlideRequest { } public BitmapRequestBuilder build() { - Drawable drawable = TintHelper.createTintedDrawable(context, DEFAULT_ERROR_IMAGE, ThemeStore.Companion.accentColor(context)); + //noinspection unchecked return createBaseRequest(builder.requestManager, builder.song, builder.ignoreMediaStore) .asBitmap() .transcode(new BitmapPaletteTranscoder(context), BitmapPaletteWrapper.class) .diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY) - .placeholder(drawable) - .error(drawable) + .error(DEFAULT_ERROR_IMAGE) .animate(DEFAULT_ANIMATION) .signature(createSignature(builder.song)); } } - - @NonNull - private static DrawableTypeRequest createBaseRequest(@NonNull RequestManager requestManager, - @NonNull Song song, - boolean ignoreMediaStore) { - if (ignoreMediaStore) { - return requestManager.load(new AudioFileCover(song.getData())); - } else { - return requestManager.loadFromMediaStore(MusicUtil.getMediaStoreAlbumCoverUri(song.getAlbumId())); - } - } - - @NonNull - private static Key createSignature(@NonNull Song song) { - return new MediaStoreSignature("", song.getDateModified(), 0); - } -} +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/ArtistGlideRequest.java b/app/src/main/java/code/name/monkey/retromusic/glide/ArtistGlideRequest.java index 1e566f8a..175c3442 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/ArtistGlideRequest.java +++ b/app/src/main/java/code/name/monkey/retromusic/glide/ArtistGlideRequest.java @@ -16,7 +16,6 @@ package code.name.monkey.retromusic.glide; import android.content.Context; import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; @@ -30,8 +29,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.request.target.Target; -import code.name.monkey.appthemehelper.ThemeStore; -import code.name.monkey.appthemehelper.util.TintHelper; import code.name.monkey.retromusic.App; import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.glide.artistimage.ArtistImage; @@ -49,25 +46,40 @@ public class ArtistGlideRequest { private static final int DEFAULT_ERROR_IMAGE = R.drawable.default_artist_art; + @NonNull + public static Key createSignature(@NonNull Artist artist) { + return ArtistSignatureUtil.getInstance(App.Companion.getContext()).getArtistSignature(artist.getName()); + } + + @NonNull + private static DrawableTypeRequest createBaseRequest(@NonNull RequestManager requestManager, + @NonNull Artist artist, + boolean noCustomImage, boolean forceDownload) { + boolean hasCustomImage = CustomArtistImageUtil.Companion.getInstance(App.Companion.getContext()) + .hasCustomArtistImage(artist); + if (noCustomImage || !hasCustomImage) { + return requestManager.load(new ArtistImage(artist.getName())); + } else { + return requestManager.load(CustomArtistImageUtil.getFile(artist)); + } + } + public static class Builder { final Artist artist; - - boolean forceDownload; - - boolean noCustomImage; - final RequestManager requestManager; - - public static Builder from(@NonNull RequestManager requestManager, Artist artist) { - return new Builder(requestManager, artist); - } + boolean forceDownload; + boolean noCustomImage; private Builder(@NonNull RequestManager requestManager, Artist artist) { this.requestManager = requestManager; this.artist = artist; } + public static Builder from(@NonNull RequestManager requestManager, Artist artist) { + return new Builder(requestManager, artist); + } + public BitmapBuilder asBitmap() { return new BitmapBuilder(this); } @@ -132,38 +144,18 @@ public class ArtistGlideRequest { } public BitmapRequestBuilder build() { - Drawable drawable = TintHelper.createTintedDrawable(context, DEFAULT_ERROR_IMAGE, ThemeStore.Companion.accentColor(context)); //noinspection unchecked return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage, builder.forceDownload) .asBitmap() .transcode(new BitmapPaletteTranscoder(context), BitmapPaletteWrapper.class) .diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY) - .placeholder(drawable) - .error(drawable) + .placeholder(DEFAULT_ERROR_IMAGE) + .error(DEFAULT_ERROR_IMAGE) .animate(DEFAULT_ANIMATION) .priority(Priority.LOW) .override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) .signature(createSignature(builder.artist)); } } - - - @NonNull - public static Key createSignature(@NonNull Artist artist) { - return ArtistSignatureUtil.getInstance(App.Companion.getContext()).getArtistSignature(artist.getName()); - } - - @NonNull - private static DrawableTypeRequest createBaseRequest(@NonNull RequestManager requestManager, - @NonNull Artist artist, - boolean noCustomImage, boolean forceDownload) { - boolean hasCustomImage = CustomArtistImageUtil.Companion.getInstance(App.Companion.getContext()) - .hasCustomArtistImage(artist); - if (noCustomImage || !hasCustomImage) { - return requestManager.load(new ArtistImage(artist.getName())); - } else { - return requestManager.load(CustomArtistImageUtil.getFile(artist)); - } - } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/BlurTransformation.kt b/app/src/main/java/code/name/monkey/retromusic/glide/BlurTransformation.kt index 969fc743..0c2af3db 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/BlurTransformation.kt +++ b/app/src/main/java/code/name/monkey/retromusic/glide/BlurTransformation.kt @@ -87,7 +87,12 @@ class BlurTransformation : BitmapTransformation { } } - override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap? { + override fun transform( + pool: BitmapPool, + toTransform: Bitmap, + outWidth: Int, + outHeight: Int + ): Bitmap? { val sampling: Int if (this.sampling == 0) { sampling = ImageUtil.calculateInSampleSize(toTransform.width, toTransform.height, 100) @@ -114,7 +119,12 @@ class BlurTransformation : BitmapTransformation { if (Build.VERSION.SDK_INT >= 17) { try { val rs = RenderScript.create(context!!.applicationContext) - val input = Allocation.createFromBitmap(rs, out, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT) + val input = Allocation.createFromBitmap( + rs, + out, + Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT + ) val output = Allocation.createTyped(rs, input.type) val script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)) diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicColoredTarget.kt b/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicColoredTarget.kt index 63a20dfb..7fbb8a12 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicColoredTarget.kt +++ b/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicColoredTarget.kt @@ -40,15 +40,20 @@ abstract class RetroMusicColoredTarget(view: ImageView) : BitmapPaletteTarget(vi onColorReady(defaultFooterColor) } - override fun onResourceReady(resource: BitmapPaletteWrapper?, glideAnimation: GlideAnimation?) { + override fun onResourceReady( + resource: BitmapPaletteWrapper?, + glideAnimation: GlideAnimation? + ) { super.onResourceReady(resource, glideAnimation) val defaultColor = defaultFooterColor resource?.let { - onColorReady(if (PreferenceUtil.getInstance(getView().context).isDominantColor) - RetroColorUtil.getDominantColor(it.bitmap, defaultColor) - else - RetroColorUtil.getColor(it.palette, defaultColor)) + onColorReady( + if (PreferenceUtil.getInstance(getView().context).isDominantColor) + RetroColorUtil.getDominantColor(it.bitmap, defaultColor) + else + RetroColorUtil.getColor(it.palette, defaultColor) + ) } } } diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicGlideModule.kt b/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicGlideModule.kt index 816a324f..078871cd 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicGlideModule.kt +++ b/app/src/main/java/code/name/monkey/retromusic/glide/RetroMusicGlideModule.kt @@ -16,7 +16,6 @@ package code.name.monkey.retromusic.glide import android.content.Context import code.name.monkey.retromusic.glide.artistimage.ArtistImage -import code.name.monkey.retromusic.glide.artistimage.ArtistImageLoader import code.name.monkey.retromusic.glide.artistimage.Factory import code.name.monkey.retromusic.glide.audiocover.AudioFileCover import code.name.monkey.retromusic.glide.audiocover.AudioFileCoverLoader @@ -30,7 +29,11 @@ class RetroMusicGlideModule : GlideModule { } override fun registerComponents(context: Context, glide: Glide) { - glide.register(AudioFileCover::class.java, InputStream::class.java, AudioFileCoverLoader.Factory()) + glide.register( + AudioFileCover::class.java, + InputStream::class.java, + AudioFileCoverLoader.Factory() + ) glide.register(ArtistImage::class.java, InputStream::class.java, Factory(context)) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/SongGlideRequest.java b/app/src/main/java/code/name/monkey/retromusic/glide/SongGlideRequest.java index 8bbfb935..acc90640 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/SongGlideRequest.java +++ b/app/src/main/java/code/name/monkey/retromusic/glide/SongGlideRequest.java @@ -16,7 +16,6 @@ package code.name.monkey.retromusic.glide; import android.content.Context; import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; @@ -29,8 +28,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.signature.MediaStoreSignature; -import code.name.monkey.appthemehelper.ThemeStore; -import code.name.monkey.appthemehelper.util.TintHelper; import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.glide.audiocover.AudioFileCover; import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder; @@ -48,21 +45,37 @@ public class SongGlideRequest { private static final int DEFAULT_ERROR_IMAGE = R.drawable.default_audio_art; private static final int DEFAULT_ANIMATION = android.R.anim.fade_in; + @NonNull + private static DrawableTypeRequest createBaseRequest(@NonNull RequestManager requestManager, + @NonNull Song song, + boolean ignoreMediaStore) { + if (ignoreMediaStore) { + return requestManager.load(new AudioFileCover(song.getData())); + } else { + return requestManager.loadFromMediaStore(MusicUtil.getMediaStoreAlbumCoverUri(song.getAlbumId())); + } + } + + @NonNull + private static Key createSignature(@NonNull Song song) { + return new MediaStoreSignature("", song.getDateModified(), 0); + } + public static class Builder { final RequestManager requestManager; final Song song; boolean ignoreMediaStore; - @NonNull - public static Builder from(@NonNull RequestManager requestManager, Song song) { - return new Builder(requestManager, song); - } - private Builder(@NonNull RequestManager requestManager, Song song) { this.requestManager = requestManager; this.song = song; } + @NonNull + public static Builder from(@NonNull RequestManager requestManager, Song song) { + return new Builder(requestManager, song); + } + @NonNull public PaletteBuilder generatePalette(@NonNull Context context) { return new PaletteBuilder(this, context); @@ -90,7 +103,6 @@ public class SongGlideRequest { return createBaseRequest(requestManager, song, ignoreMediaStore) .diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY) .error(DEFAULT_ERROR_IMAGE) - .placeholder(DEFAULT_ERROR_IMAGE) .animate(DEFAULT_ANIMATION) .signature(createSignature(song)); } @@ -109,7 +121,6 @@ public class SongGlideRequest { .asBitmap() .diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY) .error(DEFAULT_ERROR_IMAGE) - .placeholder(DEFAULT_ERROR_IMAGE) .animate(DEFAULT_ANIMATION) .signature(createSignature(builder.song)); } @@ -125,32 +136,14 @@ public class SongGlideRequest { } public BitmapRequestBuilder build() { - Drawable drawable = TintHelper.createTintedDrawable(context, DEFAULT_ERROR_IMAGE, ThemeStore.Companion.accentColor(context)); //noinspection unchecked return createBaseRequest(builder.requestManager, builder.song, builder.ignoreMediaStore) .asBitmap() .transcode(new BitmapPaletteTranscoder(context), BitmapPaletteWrapper.class) .diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY) - .placeholder(drawable) - .error(drawable) + .error(DEFAULT_ERROR_IMAGE) .animate(DEFAULT_ANIMATION) .signature(createSignature(builder.song)); } } - - @NonNull - private static DrawableTypeRequest createBaseRequest(@NonNull RequestManager requestManager, - @NonNull Song song, - boolean ignoreMediaStore) { - if (ignoreMediaStore) { - return requestManager.load(new AudioFileCover(song.getData())); - } else { - return requestManager.loadFromMediaStore(MusicUtil.getMediaStoreAlbumCoverUri(song.getAlbumId())); - } - } - - @NonNull - private static Key createSignature(@NonNull Song song) { - return new MediaStoreSignature("", song.getDateModified(), 0); - } } diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt b/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt index 6bf62d7e..0ed4e892 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt @@ -60,7 +60,10 @@ class ArtistImageFetcher( } override fun loadData(priority: Priority?): InputStream? { - if (!MusicUtil.isArtistNameUnknown(model.artistName) && PreferenceUtil.isAllowedToDownloadMetadata(context)) { + if (!MusicUtil.isArtistNameUnknown(model.artistName) && PreferenceUtil.isAllowedToDownloadMetadata( + context + ) + ) { val artists = model.artistName.split(",") val response = deezerApiService.getArtistImage(artists[0]).execute() @@ -100,7 +103,11 @@ class ArtistImageLoader( private val urlLoader: ModelLoader ) : StreamModelLoader { - override fun getResourceFetcher(model: ArtistImage, width: Int, height: Int): DataFetcher { + override fun getResourceFetcher( + model: ArtistImage, + width: Int, + height: Int + ): DataFetcher { return ArtistImageFetcher(context, deezerApiService, model, urlLoader, width, height) } } @@ -129,8 +136,15 @@ class Factory( ) } - override fun build(context: Context?, factories: GenericLoaderFactory?): ModelLoader { - return ArtistImageLoader(context!!, deezerApiService, okHttpFactory.build(context, factories)) + override fun build( + context: Context?, + factories: GenericLoaderFactory? + ): ModelLoader { + return ArtistImageLoader( + context!!, + deezerApiService, + okHttpFactory.build(context, factories) + ) } override fun teardown() { diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/audiocover/AudioFileCoverLoader.java b/app/src/main/java/code/name/monkey/retromusic/glide/audiocover/AudioFileCoverLoader.java index 591d5a35..1da3ec8c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/audiocover/AudioFileCoverLoader.java +++ b/app/src/main/java/code/name/monkey/retromusic/glide/audiocover/AudioFileCoverLoader.java @@ -25,7 +25,6 @@ import com.bumptech.glide.load.model.stream.StreamModelLoader; import java.io.InputStream; - public class AudioFileCoverLoader implements StreamModelLoader { @Override diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/palette/BitmapPaletteWrapper.java b/app/src/main/java/code/name/monkey/retromusic/glide/palette/BitmapPaletteWrapper.java index 4aa89e08..105d09f0 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/palette/BitmapPaletteWrapper.java +++ b/app/src/main/java/code/name/monkey/retromusic/glide/palette/BitmapPaletteWrapper.java @@ -15,6 +15,7 @@ package code.name.monkey.retromusic.glide.palette; import android.graphics.Bitmap; + import androidx.palette.graphics.Palette; public class BitmapPaletteWrapper { diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/HorizontalAdapterHelper.kt b/app/src/main/java/code/name/monkey/retromusic/helper/HorizontalAdapterHelper.kt index 0980a9ac..86bc78d6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/HorizontalAdapterHelper.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/HorizontalAdapterHelper.kt @@ -27,10 +27,12 @@ object HorizontalAdapterHelper { private const val TYPE_MIDDLE = 2 private const val TYPE_LAST = 3 - fun applyMarginToLayoutParams(context: Context, - layoutParams: ViewGroup.MarginLayoutParams, viewType: Int) { + fun applyMarginToLayoutParams( + context: Context, + layoutParams: ViewGroup.MarginLayoutParams, viewType: Int + ) { val listMargin = context.resources - .getDimensionPixelSize(R.dimen.now_playing_top_margin) + .getDimensionPixelSize(R.dimen.now_playing_top_margin) if (viewType == TYPE_FIRST) { layoutParams.leftMargin = listMargin } else if (viewType == TYPE_LAST) { diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt index cc40680b..22f3b83a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt @@ -16,12 +16,7 @@ package code.name.monkey.retromusic.helper import android.annotation.TargetApi import android.app.Activity -import android.content.ComponentName -import android.content.ContentResolver -import android.content.Context -import android.content.ContextWrapper -import android.content.Intent -import android.content.ServiceConnection +import android.content.* import android.database.Cursor import android.net.Uri import android.os.Build @@ -36,9 +31,7 @@ import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.PreferenceUtil import java.io.File -import java.util.ArrayList -import java.util.Random -import java.util.WeakHashMap +import java.util.* object MusicPlayerRemote { val TAG: String = MusicPlayerRemote::class.java.simpleName @@ -209,7 +202,12 @@ object MusicPlayerRemote { */ @JvmStatic fun openQueue(queue: List, startPosition: Int, startPlaying: Boolean) { - if (!tryToHandleOpenPlayingQueue(queue, startPosition, startPlaying) && musicService != null) { + if (!tryToHandleOpenPlayingQueue( + queue, + startPosition, + startPlaying + ) && musicService != null + ) { musicService?.openQueue(queue, startPosition, startPlaying) if (PreferenceUtil.getInstance(musicService).isShuffleModeOn) setShuffleMode(MusicService.SHUFFLE_MODE_NONE) @@ -226,7 +224,12 @@ object MusicPlayerRemote { startPosition = Random().nextInt(queue.size) } - if (!tryToHandleOpenPlayingQueue(queue, startPosition, startPlaying) && musicService != null) { + if (!tryToHandleOpenPlayingQueue( + queue, + startPosition, + startPlaying + ) && musicService != null + ) { openQueue(queue, startPosition, startPlaying) setShuffleMode(MusicService.SHUFFLE_MODE_SHUFFLE) } @@ -419,7 +422,10 @@ object MusicPlayerRemote { var songFile: File? = null if (uri.authority != null && uri.authority == "com.android.externalstorage.documents") { songFile = - File(Environment.getExternalStorageDirectory(), uri.path?.split(":".toRegex(), 2)?.get(1)) + File( + Environment.getExternalStorageDirectory(), + uri.path?.split(":".toRegex(), 2)?.get(1) + ) } if (songFile == null) { val path = getFilePathFromUri(musicService!!, uri) @@ -453,7 +459,8 @@ object MusicPlayerRemote { return DocumentsContract.getDocumentId(uri).split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] } - class ServiceBinder internal constructor(private val mCallback: ServiceConnection?) : ServiceConnection { + class ServiceBinder internal constructor(private val mCallback: ServiceConnection?) : + ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { val binder = service as MusicService.MusicBinder diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/SearchQueryHelper.kt b/app/src/main/java/code/name/monkey/retromusic/helper/SearchQueryHelper.kt index 78ea3e6d..4273931e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/SearchQueryHelper.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/SearchQueryHelper.kt @@ -20,7 +20,7 @@ import android.os.Bundle import android.provider.MediaStore import code.name.monkey.retromusic.loaders.SongLoader import code.name.monkey.retromusic.model.Song -import java.util.ArrayList +import java.util.* object SearchQueryHelper { private const val TITLE_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.TITLE + ") = ?" @@ -41,7 +41,11 @@ object SearchQueryHelper { SongLoader.makeSongCursor( context, ARTIST_SELECTION + AND + ALBUM_SELECTION + AND + TITLE_SELECTION, - arrayOf(artistName.toLowerCase(), albumName.toLowerCase(), titleName.toLowerCase()) + arrayOf( + artistName.toLowerCase(), + albumName.toLowerCase(), + titleName.toLowerCase() + ) ) ) } @@ -109,16 +113,34 @@ object SearchQueryHelper { return songs } songs = - SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION, arrayOf(query.toLowerCase()))) + SongLoader.getSongs( + SongLoader.makeSongCursor( + context, + ARTIST_SELECTION, + arrayOf(query.toLowerCase()) + ) + ) if (songs.isNotEmpty()) { return songs } - songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ALBUM_SELECTION, arrayOf(query.toLowerCase()))) + songs = SongLoader.getSongs( + SongLoader.makeSongCursor( + context, + ALBUM_SELECTION, + arrayOf(query.toLowerCase()) + ) + ) if (songs.isNotEmpty()) { return songs } - songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, TITLE_SELECTION, arrayOf(query.toLowerCase()))) + songs = SongLoader.getSongs( + SongLoader.makeSongCursor( + context, + TITLE_SELECTION, + arrayOf(query.toLowerCase()) + ) + ) return if (songs.isNotEmpty()) { songs } else ArrayList() diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/StackBlur.java b/app/src/main/java/code/name/monkey/retromusic/helper/StackBlur.java index 3e812e8a..112b554b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/StackBlur.java +++ b/app/src/main/java/code/name/monkey/retromusic/helper/StackBlur.java @@ -24,12 +24,12 @@ import java.util.concurrent.Executors; * on the left side of the stack. * * @author Enrique López Mañas - * http://www.neo-tech.es - *

- * Author of the original algorithm: Mario Klingemann - *

- * Based heavily on http://vitiy.info/Code/stackblur.cpp - * See http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ + * http://www.neo-tech.es + *

+ * Author of the original algorithm: Mario Klingemann + *

+ * Based heavily on http://vitiy.info/Code/stackblur.cpp + * See http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ * @copyright: Enrique López Mañas * @license: Apache License 2.0 */ diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/menu/GenreMenuHelper.kt b/app/src/main/java/code/name/monkey/retromusic/helper/menu/GenreMenuHelper.kt index 50610499..af790d95 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/menu/GenreMenuHelper.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/menu/GenreMenuHelper.kt @@ -39,7 +39,7 @@ object GenreMenuHelper { } R.id.action_add_to_playlist -> { AddToPlaylistDialog.create(getGenreSongs(activity, genre)) - .show(activity.supportFragmentManager, "ADD_PLAYLIST") + .show(activity.supportFragmentManager, "ADD_PLAYLIST") return true } R.id.action_add_to_current_playing -> { diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/menu/PlaylistMenuHelper.kt b/app/src/main/java/code/name/monkey/retromusic/helper/menu/PlaylistMenuHelper.kt index 082500dc..ef9729dc 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/menu/PlaylistMenuHelper.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/menu/PlaylistMenuHelper.kt @@ -37,8 +37,10 @@ import java.util.* object PlaylistMenuHelper { - fun handleMenuClick(activity: AppCompatActivity, - playlist: Playlist, item: MenuItem): Boolean { + fun handleMenuClick( + activity: AppCompatActivity, + playlist: Playlist, item: MenuItem + ): Boolean { when (item.itemId) { R.id.action_play -> { MusicPlayerRemote.openQueue(getPlaylistSongs(activity, playlist), 9, true) @@ -50,7 +52,7 @@ object PlaylistMenuHelper { } R.id.action_add_to_playlist -> { AddToPlaylistDialog.create(getPlaylistSongs(activity, playlist)) - .show(activity.supportFragmentManager, "ADD_PLAYLIST") + .show(activity.supportFragmentManager, "ADD_PLAYLIST") return true } R.id.action_add_to_current_playing -> { @@ -59,12 +61,12 @@ object PlaylistMenuHelper { } R.id.action_rename_playlist -> { RenamePlaylistDialog.create(playlist.id.toLong()) - .show(activity.supportFragmentManager, "RENAME_PLAYLIST") + .show(activity.supportFragmentManager, "RENAME_PLAYLIST") return true } R.id.action_delete_playlist -> { DeletePlaylistDialog.create(playlist) - .show(activity.supportFragmentManager, "DELETE_PLAYLIST") + .show(activity.supportFragmentManager, "DELETE_PLAYLIST") return true } R.id.action_save_playlist -> { @@ -75,8 +77,10 @@ object PlaylistMenuHelper { return false } - private fun getPlaylistSongs(activity: Activity, - playlist: Playlist): ArrayList { + private fun getPlaylistSongs( + activity: Activity, + playlist: Playlist + ): ArrayList { return if (playlist is AbsCustomPlaylist) { playlist.getSongs(activity) } else { @@ -84,11 +88,16 @@ object PlaylistMenuHelper { } } - private class SavePlaylistAsyncTask internal constructor(context: Context) : WeakContextAsyncTask(context) { + private class SavePlaylistAsyncTask internal constructor(context: Context) : + WeakContextAsyncTask(context) { override fun doInBackground(vararg params: Playlist): String { - return String.format(App.getContext().getString(R.string - .saved_playlist_to), PlaylistsUtil.savePlaylist(App.getContext(), params[0])) + return String.format( + App.getContext().getString( + R.string + .saved_playlist_to + ), PlaylistsUtil.savePlaylist(App.getContext(), params[0]) + ) } override fun onPostExecute(string: String) { diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongMenuHelper.kt b/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongMenuHelper.kt index bc125739..c2b5f5ff 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongMenuHelper.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongMenuHelper.kt @@ -60,7 +60,8 @@ object SongMenuHelper { return true } R.id.action_add_to_playlist -> { - AddToPlaylistDialog.create(song).show(activity.supportFragmentManager, "ADD_PLAYLIST") + AddToPlaylistDialog.create(song) + .show(activity.supportFragmentManager, "ADD_PLAYLIST") return true } R.id.action_play_next -> { diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongsMenuHelper.kt b/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongsMenuHelper.kt index cd0af61e..36d110f5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongsMenuHelper.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/menu/SongsMenuHelper.kt @@ -25,7 +25,11 @@ import java.util.* object SongsMenuHelper { - fun handleMenuClick(activity: FragmentActivity, songs: ArrayList, menuItemId: Int): Boolean { + fun handleMenuClick( + activity: FragmentActivity, + songs: ArrayList, + menuItemId: Int + ): Boolean { when (menuItemId) { R.id.action_play_next -> { MusicPlayerRemote.playNext(songs) @@ -36,11 +40,13 @@ object SongsMenuHelper { return true } R.id.action_add_to_playlist -> { - AddToPlaylistDialog.create(songs).show(activity.supportFragmentManager, "ADD_PLAYLIST") + AddToPlaylistDialog.create(songs) + .show(activity.supportFragmentManager, "ADD_PLAYLIST") return true } R.id.action_delete_from_device -> { - DeleteSongsDialog.create(songs).show(activity.supportFragmentManager, "DELETE_SONGS") + DeleteSongsDialog.create(songs) + .show(activity.supportFragmentManager, "DELETE_SONGS") return true } } diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/AlbumLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/AlbumLoader.kt index d28fb1ae..49342d0d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/AlbumLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/AlbumLoader.kt @@ -19,7 +19,10 @@ import android.provider.MediaStore.Audio.AudioColumns import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.util.PreferenceUtil -import java.util.Comparator +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.isNotEmpty +import kotlin.collections.sortWith /** @@ -29,42 +32,54 @@ import java.util.Comparator object AlbumLoader { fun getAlbums( - context: Context, - query: String + context: Context, + query: String ): ArrayList { - val songs = SongLoader.getSongs(SongLoader.makeSongCursor( + val songs = SongLoader.getSongs( + SongLoader.makeSongCursor( context, AudioColumns.ALBUM + " LIKE ?", arrayOf("%$query%"), - getSongLoaderSortOrder(context)) + getSongLoaderSortOrder(context) + ) ) return splitIntoAlbums(songs) } + @JvmStatic fun getAlbum( - context: Context, - albumId: Int + context: Context, + albumId: Int ): Album { val songs = SongLoader.getSongs( - SongLoader.makeSongCursor( - context, - AudioColumns.ALBUM_ID + "=?", - arrayOf(albumId.toString()), - getSongLoaderSortOrder(context))) + SongLoader.makeSongCursor( + context, + AudioColumns.ALBUM_ID + "=?", + arrayOf(albumId.toString()), + getSongLoaderSortOrder(context) + ) + ) val album = Album(songs) sortSongsByTrackNumber(album) return album } fun getAllAlbums( - context: Context + context: Context ): ArrayList { - val songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, null, null, getSongLoaderSortOrder(context))) + val songs = SongLoader.getSongs( + SongLoader.makeSongCursor( + context, + null, + null, + getSongLoaderSortOrder(context) + ) + ) return splitIntoAlbums(songs) } fun splitIntoAlbums( - songs: ArrayList? + songs: ArrayList? ): ArrayList { val albums = ArrayList() if (songs != null) { @@ -79,8 +94,8 @@ object AlbumLoader { } private fun getOrCreateAlbum( - albums: ArrayList, - albumId: Int + albums: ArrayList, + albumId: Int ): Album { for (album in albums) { if (album.songs!!.isNotEmpty() && album.songs[0].albumId == albumId) { @@ -97,6 +112,8 @@ object AlbumLoader { } private fun getSongLoaderSortOrder(context: Context): String { - return PreferenceUtil.getInstance(context).albumSortOrder + ", " + PreferenceUtil.getInstance(context).albumSongSortOrder + return PreferenceUtil.getInstance(context).albumSortOrder + ", " + PreferenceUtil.getInstance( + context + ).albumSongSortOrder } } diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/ArtistLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/ArtistLoader.kt index cd994be1..cde5b43f 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/ArtistLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/ArtistLoader.kt @@ -22,7 +22,9 @@ import code.name.monkey.retromusic.util.PreferenceUtil object ArtistLoader { private fun getSongLoaderSortOrder(context: Context): String { - return PreferenceUtil.getInstance(context).artistSortOrder + ", " + PreferenceUtil.getInstance(context).artistAlbumSortOrder + ", " + PreferenceUtil.getInstance( + return PreferenceUtil.getInstance(context).artistSortOrder + ", " + PreferenceUtil.getInstance( + context + ).artistAlbumSortOrder + ", " + PreferenceUtil.getInstance( context ).albumSongSortOrder } diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/GenreLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/GenreLoader.kt index 09afd12a..c92cde62 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/GenreLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/GenreLoader.kt @@ -82,8 +82,9 @@ object GenreLoader { private fun makeAllSongsWithGenreCursor(context: Context): Cursor? { try { return context.contentResolver.query( - Uri.parse("content://media/external/audio/genres/all/members"), - arrayOf(Genres.Members.AUDIO_ID), null, null, null) + Uri.parse("content://media/external/audio/genres/all/members"), + arrayOf(Genres.Members.AUDIO_ID), null, null, null + ) } catch (e: SecurityException) { return null } @@ -93,8 +94,12 @@ object GenreLoader { private fun makeGenreSongCursor(context: Context, genreId: Int): Cursor? { try { return context.contentResolver.query( - Genres.Members.getContentUri("external", genreId.toLong()), - baseProjection, BASE_SELECTION, null, PreferenceUtil.getInstance(context).songSortOrder) + Genres.Members.getContentUri("external", genreId.toLong()), + baseProjection, + BASE_SELECTION, + null, + PreferenceUtil.getInstance(context).songSortOrder + ) } catch (e: SecurityException) { return null } @@ -112,7 +117,11 @@ object GenreLoader { } else { // try to remove the empty genre from the media store try { - context.contentResolver.delete(Genres.EXTERNAL_CONTENT_URI, Genres._ID + " == " + genre.id, null) + context.contentResolver.delete( + Genres.EXTERNAL_CONTENT_URI, + Genres._ID + " == " + genre.id, + null + ) } catch (e: Exception) { e.printStackTrace() } @@ -140,7 +149,13 @@ object GenreLoader { private fun makeGenreCursor(context: Context): Cursor? { val projection = arrayOf(Genres._ID, Genres.NAME) try { - return context.contentResolver.query(Genres.EXTERNAL_CONTENT_URI, projection, null, null, PreferenceUtil.getInstance(context).genreSortOrder) + return context.contentResolver.query( + Genres.EXTERNAL_CONTENT_URI, + projection, + null, + null, + PreferenceUtil.getInstance(context).genreSortOrder + ) } catch (e: SecurityException) { return null } diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/LastAddedSongsLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/LastAddedSongsLoader.kt index 358bd595..3a9e2d50 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/LastAddedSongsLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/LastAddedSongsLoader.kt @@ -36,10 +36,11 @@ object LastAddedSongsLoader { val cutoff = PreferenceUtil.getInstance(context).lastAddedCutoff return SongLoader.makeSongCursor( - context, - MediaStore.Audio.Media.DATE_ADDED + ">?", - arrayOf(cutoff.toString()), - MediaStore.Audio.Media.DATE_ADDED + " DESC") + context, + MediaStore.Audio.Media.DATE_ADDED + ">?", + arrayOf(cutoff.toString()), + MediaStore.Audio.Media.DATE_ADDED + " DESC" + ) } fun getLastAddedAlbums(context: Context): ArrayList { diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistLoader.kt index 1bfa9334..12eff6df 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistLoader.kt @@ -20,7 +20,7 @@ import android.provider.BaseColumns import android.provider.MediaStore import android.provider.MediaStore.Audio.PlaylistsColumns import code.name.monkey.retromusic.model.Playlist -import java.util.ArrayList +import java.util.* /** * Created by hemanths on 16/08/17. diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistSongsLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistSongsLoader.kt index c6a3c297..546f538f 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistSongsLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/PlaylistSongsLoader.kt @@ -23,7 +23,7 @@ import code.name.monkey.retromusic.model.AbsCustomPlaylist import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.model.PlaylistSong import code.name.monkey.retromusic.model.Song -import java.util.ArrayList +import java.util.* /** * Created by hemanths on 16/08/17. @@ -38,6 +38,7 @@ object PlaylistSongsLoader { return (playlist as? AbsCustomPlaylist)?.getSongs(context) ?: getPlaylistSongList(context, playlist.id) } + @JvmStatic fun getPlaylistSongList(context: Context, playlistId: Int): ArrayList { val songs = arrayListOf() diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/SearchLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/SearchLoader.kt index cd42dd97..d13990ad 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/SearchLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/SearchLoader.kt @@ -17,7 +17,7 @@ package code.name.monkey.retromusic.loaders import android.content.Context import code.name.monkey.retromusic.R import code.name.monkey.retromusic.model.Genre -import java.util.Locale +import java.util.* object SearchLoader { fun searchAll(context: Context, query: String?): MutableList { diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/SongLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/SongLoader.kt index e03b6ef7..aa9fc369 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/SongLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/SongLoader.kt @@ -23,7 +23,7 @@ import code.name.monkey.retromusic.Constants.baseProjection import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.providers.BlacklistStore import code.name.monkey.retromusic.util.PreferenceUtil -import java.util.ArrayList +import java.util.* /** * Created by hemanths on 10/08/17. diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/SortedCursor.java b/app/src/main/java/code/name/monkey/retromusic/loaders/SortedCursor.java index 2a509570..54049643 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/SortedCursor.java +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/SortedCursor.java @@ -15,6 +15,7 @@ package code.name.monkey.retromusic.loaders; import android.database.AbstractCursor; import android.database.Cursor; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/SortedLongCursor.java b/app/src/main/java/code/name/monkey/retromusic/loaders/SortedLongCursor.java index 4189dfc1..8368c040 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/SortedLongCursor.java +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/SortedLongCursor.java @@ -15,6 +15,7 @@ package code.name.monkey.retromusic.loaders; import android.database.AbstractCursor; import android.database.Cursor; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/app/src/main/java/code/name/monkey/retromusic/loaders/TopAndRecentlyPlayedTracksLoader.kt b/app/src/main/java/code/name/monkey/retromusic/loaders/TopAndRecentlyPlayedTracksLoader.kt index d7f6bee3..0948d517 100644 --- a/app/src/main/java/code/name/monkey/retromusic/loaders/TopAndRecentlyPlayedTracksLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/loaders/TopAndRecentlyPlayedTracksLoader.kt @@ -23,7 +23,7 @@ import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.providers.HistoryStore import code.name.monkey.retromusic.providers.SongPlayCountStore -import java.util.ArrayList +import java.util.* /** * Created by hemanths on 16/08/17. diff --git a/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcHelper.java b/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcHelper.java index d2c05193..385b7856 100644 --- a/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcHelper.java +++ b/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcHelper.java @@ -127,10 +127,10 @@ public class LrcHelper { String mil = timeMatcher.group(3); Lrc lrc = new Lrc(); if (content != null && content.length() != 0) { - if(Integer.parseInt(mil)< 100){ - lrc.setTime(Long.parseLong(min) * 60 * 1000 + Long.parseLong(sec) * 1000 - + Long.parseLong(mil) * 10);} - else{ + if (Integer.parseInt(mil) < 100) { + lrc.setTime(Long.parseLong(min) * 60 * 1000 + Long.parseLong(sec) * 1000 + + Long.parseLong(mil) * 10); + } else { lrc.setTime(Long.parseLong(min) * 60 * 1000 + Long.parseLong(sec) * 1000 + Long.parseLong(mil) ); diff --git a/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcView.kt b/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcView.kt index eb00f0db..9541e1c6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcView.kt +++ b/app/src/main/java/code/name/monkey/retromusic/lyrics/LrcView.kt @@ -47,7 +47,11 @@ import java.util.* * Blog : http://www.jianshu.com/u/e76853f863a9 * Email : freedompaladin@gmail.com */ -class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) { +class LrcView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { private var mLrcData: MutableList? = null private var mTextPaint: TextPaint? = null private var mDefaultContent: String? = null @@ -142,25 +146,55 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = private fun init(context: Context, attrs: AttributeSet?) { val typedArray = context.obtainStyledAttributes(attrs, R.styleable.LrcView) - mLrcTextSize = typedArray.getDimension(R.styleable.LrcView_lrcTextSize, sp2px(context, 15f).toFloat()) - mLrcLineSpaceHeight = typedArray.getDimension(R.styleable.LrcView_lrcLineSpaceSize, dp2px(context, 20f).toFloat()) + mLrcTextSize = + typedArray.getDimension(R.styleable.LrcView_lrcTextSize, sp2px(context, 15f).toFloat()) + mLrcLineSpaceHeight = typedArray.getDimension( + R.styleable.LrcView_lrcLineSpaceSize, + dp2px(context, 20f).toFloat() + ) mTouchDelay = typedArray.getInt(R.styleable.LrcView_lrcTouchDelay, 3500) mIndicatorTouchDelay = typedArray.getInt(R.styleable.LrcView_indicatorTouchDelay, 2500) mNormalColor = typedArray.getColor(R.styleable.LrcView_lrcNormalTextColor, Color.GRAY) - mCurrentPlayLineColor = typedArray.getColor(R.styleable.LrcView_lrcCurrentTextColor, Color.BLUE) - mNoLrcTextSize = typedArray.getDimension(R.styleable.LrcView_noLrcTextSize, dp2px(context, 20f).toFloat()) + mCurrentPlayLineColor = + typedArray.getColor(R.styleable.LrcView_lrcCurrentTextColor, Color.BLUE) + mNoLrcTextSize = typedArray.getDimension( + R.styleable.LrcView_noLrcTextSize, + dp2px(context, 20f).toFloat() + ) mNoLrcTextColor = typedArray.getColor(R.styleable.LrcView_noLrcTextColor, Color.BLACK) - mIndicatorLineWidth = typedArray.getDimension(R.styleable.LrcView_indicatorLineHeight, dp2px(context, 0.5f).toFloat()) - mIndicatorTextSize = typedArray.getDimension(R.styleable.LrcView_indicatorTextSize, sp2px(context, 13f).toFloat()) - mIndicatorTextColor = typedArray.getColor(R.styleable.LrcView_indicatorTextColor, Color.GRAY) - mCurrentIndicateLineTextColor = typedArray.getColor(R.styleable.LrcView_currentIndicateLrcColor, Color.GRAY) - mIndicatorLineColor = typedArray.getColor(R.styleable.LrcView_indicatorLineColor, Color.GRAY) - mIndicatorMargin = typedArray.getDimension(R.styleable.LrcView_indicatorStartEndMargin, dp2px(context, 5f).toFloat()) - mIconLineGap = typedArray.getDimension(R.styleable.LrcView_iconLineGap, dp2px(context, 3f).toFloat()) - mIconWidth = typedArray.getDimension(R.styleable.LrcView_playIconWidth, dp2px(context, 20f).toFloat()) - mIconHeight = typedArray.getDimension(R.styleable.LrcView_playIconHeight, dp2px(context, 20f).toFloat()) + mIndicatorLineWidth = typedArray.getDimension( + R.styleable.LrcView_indicatorLineHeight, + dp2px(context, 0.5f).toFloat() + ) + mIndicatorTextSize = typedArray.getDimension( + R.styleable.LrcView_indicatorTextSize, + sp2px(context, 13f).toFloat() + ) + mIndicatorTextColor = + typedArray.getColor(R.styleable.LrcView_indicatorTextColor, Color.GRAY) + mCurrentIndicateLineTextColor = + typedArray.getColor(R.styleable.LrcView_currentIndicateLrcColor, Color.GRAY) + mIndicatorLineColor = + typedArray.getColor(R.styleable.LrcView_indicatorLineColor, Color.GRAY) + mIndicatorMargin = typedArray.getDimension( + R.styleable.LrcView_indicatorStartEndMargin, + dp2px(context, 5f).toFloat() + ) + mIconLineGap = + typedArray.getDimension(R.styleable.LrcView_iconLineGap, dp2px(context, 3f).toFloat()) + mIconWidth = typedArray.getDimension( + R.styleable.LrcView_playIconWidth, + dp2px(context, 20f).toFloat() + ) + mIconHeight = typedArray.getDimension( + R.styleable.LrcView_playIconHeight, + dp2px(context, 20f).toFloat() + ) mPlayDrawable = typedArray.getDrawable(R.styleable.LrcView_playIcon) - mPlayDrawable = if (mPlayDrawable == null) ContextCompat.getDrawable(context, R.drawable.ic_play_arrow_white_24dp) else mPlayDrawable + mPlayDrawable = if (mPlayDrawable == null) ContextCompat.getDrawable( + context, + R.drawable.ic_play_arrow_white_24dp + ) else mPlayDrawable typedArray.recycle() setupConfigs(context) @@ -238,12 +272,20 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = val time = mLrcData!![indicatePosition].time val timeWidth = mIndicatorPaint!!.measureText(LrcHelper.formatTime(time)) mIndicatorPaint!!.color = mIndicatorLineColor - canvas.drawLine(mPlayRect!!.right + mIconLineGap, (height / 2).toFloat(), - width - timeWidth * 1.3f, (height / 2).toFloat(), mIndicatorPaint!!) + canvas.drawLine( + mPlayRect!!.right + mIconLineGap, (height / 2).toFloat(), + width - timeWidth * 1.3f, (height / 2).toFloat(), mIndicatorPaint!! + ) val baseX = (width - timeWidth * 1.1f).toInt() - val baseline = (height / 2).toFloat() - (mIndicatorPaint!!.descent() - mIndicatorPaint!!.ascent()) / 2 - mIndicatorPaint!!.ascent() + val baseline = + (height / 2).toFloat() - (mIndicatorPaint!!.descent() - mIndicatorPaint!!.ascent()) / 2 - mIndicatorPaint!!.ascent() mIndicatorPaint!!.color = mIndicatorTextColor - canvas.drawText(LrcHelper.formatTime(time), baseX.toFloat(), baseline, mIndicatorPaint!!) + canvas.drawText( + LrcHelper.formatTime(time), + baseX.toFloat(), + baseline, + mIndicatorPaint!! + ) } } @@ -257,7 +299,15 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = var staticLayout: StaticLayout? = mLrcMap[text] if (staticLayout == null) { mTextPaint!!.textSize = mLrcTextSize - staticLayout = StaticLayout(text, mTextPaint, lrcWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false) + staticLayout = StaticLayout( + text, + mTextPaint, + lrcWidth, + Layout.Alignment.ALIGN_NORMAL, + 1f, + 0f, + false + ) mLrcMap[text] = staticLayout } canvas.save() @@ -272,8 +322,10 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = mTextPaint!!.color = mNoLrcTextColor mTextPaint!!.textSize = mNoLrcTextSize canvas.save() - val staticLayout = StaticLayout(mDefaultContent, mTextPaint, - lrcWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false) + val staticLayout = StaticLayout( + mDefaultContent, mTextPaint, + lrcWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false + ) val margin = dip2px(context, 16f).toFloat(); canvas.translate(margin, margin) staticLayout.draw(canvas) @@ -335,8 +387,10 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = var staticLayout: StaticLayout? = mStaticLayoutHashMap[text] if (staticLayout == null) { mTextPaint!!.textSize = mLrcTextSize - staticLayout = StaticLayout(text, mTextPaint, - lrcWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false) + staticLayout = StaticLayout( + text, mTextPaint, + lrcWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false + ) mStaticLayoutHashMap[text] = staticLayout } return staticLayout.height.toFloat() @@ -405,20 +459,30 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = private fun handleActionUp(event: MotionEvent) { if (isEnableShowIndicator) { - ViewCompat.postOnAnimationDelayed(this@LrcView, mHideIndicatorRunnable, mIndicatorTouchDelay.toLong()) + ViewCompat.postOnAnimationDelayed( + this@LrcView, + mHideIndicatorRunnable, + mIndicatorTouchDelay.toLong() + ) } if (isShowTimeIndicator && mPlayRect != null && onClickPlayButton(event)) { isShowTimeIndicator = false invalidateView() if (mOnPlayIndicatorLineListener != null) { - mOnPlayIndicatorLineListener!!.onPlay(mLrcData!![indicatePosition].time, - mLrcData!![indicatePosition].text) + mOnPlayIndicatorLineListener!!.onPlay( + mLrcData!![indicatePosition].time, + mLrcData!![indicatePosition].text + ) } } if (overScrolled() && mOffset < 0) { scrollToPosition(0) if (isAutoAdjustPosition) { - ViewCompat.postOnAnimationDelayed(this@LrcView, mScrollRunnable, mTouchDelay.toLong()) + ViewCompat.postOnAnimationDelayed( + this@LrcView, + mScrollRunnable, + mTouchDelay.toLong() + ) } return } @@ -426,7 +490,11 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = if (overScrolled() && mOffset > getItemOffsetY(lrcCount - 1)) { scrollToPosition(lrcCount - 1) if (isAutoAdjustPosition) { - ViewCompat.postOnAnimationDelayed(this@LrcView, mScrollRunnable, mTouchDelay.toLong()) + ViewCompat.postOnAnimationDelayed( + this@LrcView, + mScrollRunnable, + mTouchDelay.toLong() + ) } return } @@ -435,9 +503,11 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = val YVelocity = mVelocityTracker!!.yVelocity val absYVelocity = Math.abs(YVelocity) if (absYVelocity > mMinimumFlingVelocity) { - mOverScroller!!.fling(0, mOffset.toInt(), 0, (-YVelocity).toInt(), 0, - 0, 0, getItemOffsetY(lrcCount - 1).toInt(), - 0, getTextHeight(0).toInt()) + mOverScroller!!.fling( + 0, mOffset.toInt(), 0, (-YVelocity).toInt(), 0, + 0, 0, getItemOffsetY(lrcCount - 1).toInt(), + 0, getTextHeight(0).toInt() + ) invalidateView() } releaseVelocityTracker() @@ -493,13 +563,17 @@ class LrcView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = } fun dp2px(context: Context, dpVal: Float): Int { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - dpVal, context.resources.displayMetrics).toInt() + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dpVal, context.resources.displayMetrics + ).toInt() } fun sp2px(context: Context, spVal: Float): Int { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, - spVal, context.resources.displayMetrics).toInt() + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + spVal, context.resources.displayMetrics + ).toInt() } /** diff --git a/app/src/main/java/code/name/monkey/retromusic/misc/AsyncSearchResultLoader.kt b/app/src/main/java/code/name/monkey/retromusic/misc/AsyncSearchResultLoader.kt index a9c9486a..4127292e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/misc/AsyncSearchResultLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/misc/AsyncSearchResultLoader.kt @@ -22,7 +22,8 @@ import code.name.monkey.retromusic.loaders.ArtistLoader import code.name.monkey.retromusic.loaders.SongLoader import java.util.* -internal class AsyncSearchResultLoader(context: Context, private val query: String) : WrappedAsyncTaskLoader>(context) { +internal class AsyncSearchResultLoader(context: Context, private val query: String) : + WrappedAsyncTaskLoader>(context) { override fun loadInBackground(): List? { val results = ArrayList() diff --git a/app/src/main/java/code/name/monkey/retromusic/misc/CustomFragmentStatePagerAdapter.java b/app/src/main/java/code/name/monkey/retromusic/misc/CustomFragmentStatePagerAdapter.java index f9e68b65..31ce1874 100644 --- a/app/src/main/java/code/name/monkey/retromusic/misc/CustomFragmentStatePagerAdapter.java +++ b/app/src/main/java/code/name/monkey/retromusic/misc/CustomFragmentStatePagerAdapter.java @@ -16,6 +16,10 @@ package code.name.monkey.retromusic.misc; import android.os.Bundle; import android.os.Parcelable; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; + import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -23,10 +27,6 @@ import androidx.fragment.app.FragmentPagerAdapter; import androidx.fragment.app.FragmentTransaction; import androidx.viewpager.widget.PagerAdapter; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; - import java.util.ArrayList; /** diff --git a/app/src/main/java/code/name/monkey/retromusic/misc/DialogAsyncTask.java b/app/src/main/java/code/name/monkey/retromusic/misc/DialogAsyncTask.java index 2a2026ce..88e38762 100644 --- a/app/src/main/java/code/name/monkey/retromusic/misc/DialogAsyncTask.java +++ b/app/src/main/java/code/name/monkey/retromusic/misc/DialogAsyncTask.java @@ -17,6 +17,7 @@ package code.name.monkey.retromusic.misc; import android.app.Dialog; import android.content.Context; import android.os.Handler; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/app/src/main/java/code/name/monkey/retromusic/misc/UpdateToastMediaScannerCompletionListener.java b/app/src/main/java/code/name/monkey/retromusic/misc/UpdateToastMediaScannerCompletionListener.java index 98b52dd1..84aa17c1 100644 --- a/app/src/main/java/code/name/monkey/retromusic/misc/UpdateToastMediaScannerCompletionListener.java +++ b/app/src/main/java/code/name/monkey/retromusic/misc/UpdateToastMediaScannerCompletionListener.java @@ -19,9 +19,11 @@ import android.app.Activity; import android.media.MediaScannerConnection; import android.net.Uri; import android.widget.Toast; -import code.name.monkey.retromusic.R; + import java.lang.ref.WeakReference; +import code.name.monkey.retromusic.R; + /** * @author Karim Abou Zeid (kabouzeid) */ @@ -30,15 +32,10 @@ public class UpdateToastMediaScannerCompletionListener implements MediaScannerCo private final WeakReference activityWeakReference; private final String couldNotScanFiles; - - private int failed = 0; - - private int scanned = 0; - private final String scannedFiles; - private final String[] toBeScanned; - + private int failed = 0; + private int scanned = 0; private Toast toast; @SuppressLint("ShowToast") diff --git a/app/src/main/java/code/name/monkey/retromusic/misc/WeakContextAsyncTask.kt b/app/src/main/java/code/name/monkey/retromusic/misc/WeakContextAsyncTask.kt index f81a3dce..9b9b4896 100644 --- a/app/src/main/java/code/name/monkey/retromusic/misc/WeakContextAsyncTask.kt +++ b/app/src/main/java/code/name/monkey/retromusic/misc/WeakContextAsyncTask.kt @@ -1 +1 @@ -/* * Copyright (c) 2019 Hemanth Savarala. * * Licensed under the GNU General Public License v3 * * This is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by * the Free Software Foundation either version 3 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ package code.name.monkey.retromusic.misc import android.content.Context import android.os.AsyncTask import java.lang.ref.WeakReference abstract class WeakContextAsyncTask(context: Context) : AsyncTask() { private val contextWeakReference: WeakReference = WeakReference(context) protected val context: Context? get() = contextWeakReference.get() } \ No newline at end of file +/* * Copyright (c) 2019 Hemanth Savarala. * * Licensed under the GNU General Public License v3 * * This is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by * the Free Software Foundation either version 3 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ package code.name.monkey.retromusic.misc import android.content.Context import android.os.AsyncTask import java.lang.ref.WeakReference abstract class WeakContextAsyncTask(context: Context) : AsyncTask() { private val contextWeakReference: WeakReference = WeakReference(context) protected val context: Context? get() = contextWeakReference.get() } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/misc/WrappedAsyncTaskLoader.kt b/app/src/main/java/code/name/monkey/retromusic/misc/WrappedAsyncTaskLoader.kt index 6c717bea..b798cc52 100644 --- a/app/src/main/java/code/name/monkey/retromusic/misc/WrappedAsyncTaskLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/misc/WrappedAsyncTaskLoader.kt @@ -29,7 +29,7 @@ abstract class WrappedAsyncTaskLoader * * @param context The [Context] to use. */ -(context: Context) : AsyncTaskLoader(context) { + (context: Context) : AsyncTaskLoader(context) { private var mData: D? = null diff --git a/app/src/main/java/code/name/monkey/retromusic/model/AbsCustomPlaylist.java b/app/src/main/java/code/name/monkey/retromusic/model/AbsCustomPlaylist.java index 367e309b..819371b7 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/AbsCustomPlaylist.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/AbsCustomPlaylist.java @@ -16,10 +16,13 @@ package code.name.monkey.retromusic.model; import android.content.Context; import android.os.Parcel; + import androidx.annotation.NonNull; -import java.util.ArrayList; + import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; + /** * @author Karim Abou Zeid (kabouzeid) */ diff --git a/app/src/main/java/code/name/monkey/retromusic/model/Album.kt b/app/src/main/java/code/name/monkey/retromusic/model/Album.kt index 3796b900..4e5e35a1 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/Album.kt +++ b/app/src/main/java/code/name/monkey/retromusic/model/Album.kt @@ -14,7 +14,7 @@ package code.name.monkey.retromusic.model -import java.util.ArrayList +import java.util.* class Album { diff --git a/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt b/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt index 8d8462ef..5cad27b1 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt +++ b/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt @@ -15,7 +15,7 @@ package code.name.monkey.retromusic.model import code.name.monkey.retromusic.util.MusicUtil -import java.util.ArrayList +import java.util.* class Artist { val albums: ArrayList? diff --git a/app/src/main/java/code/name/monkey/retromusic/model/CategoryInfo.java b/app/src/main/java/code/name/monkey/retromusic/model/CategoryInfo.java index fd90a013..db5b6d63 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/CategoryInfo.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/CategoryInfo.java @@ -16,11 +16,45 @@ package code.name.monkey.retromusic.model; import android.os.Parcel; import android.os.Parcelable; + import code.name.monkey.retromusic.R; public class CategoryInfo implements Parcelable { + public static final Creator CREATOR = new Creator() { + public CategoryInfo createFromParcel(Parcel source) { + return new CategoryInfo(source); + } + + public CategoryInfo[] newArray(int size) { + return new CategoryInfo[size]; + } + }; + public Category category; + public boolean visible; + + public CategoryInfo(Category category, boolean visible) { + this.category = category; + this.visible = visible; + } + + + private CategoryInfo(Parcel source) { + category = (Category) source.readSerializable(); + visible = source.readInt() == 1; + } + + @Override + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeSerializable(category); + dest.writeInt(visible ? 1 : 0); + } + public enum Category { HOME(R.id.action_home, R.string.home, R.drawable.ic_home_white_24dp), SONGS(R.id.action_song, R.string.songs, R.drawable.ic_audiotrack_white_24dp), @@ -43,39 +77,4 @@ public class CategoryInfo implements Parcelable { this.icon = icon; } } - - public static final Creator CREATOR = new Creator() { - public CategoryInfo createFromParcel(Parcel source) { - return new CategoryInfo(source); - } - - public CategoryInfo[] newArray(int size) { - return new CategoryInfo[size]; - } - }; - - public Category category; - - public boolean visible; - - - public CategoryInfo(Category category, boolean visible) { - this.category = category; - this.visible = visible; - } - - private CategoryInfo(Parcel source) { - category = (Category) source.readSerializable(); - visible = source.readInt() == 1; - } - - @Override - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeSerializable(category); - dest.writeInt(visible ? 1 : 0); - } } diff --git a/app/src/main/java/code/name/monkey/retromusic/model/Playlist.java b/app/src/main/java/code/name/monkey/retromusic/model/Playlist.java index ae9a6ee1..2b0af369 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/Playlist.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/Playlist.java @@ -17,10 +17,13 @@ package code.name.monkey.retromusic.model; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; + import androidx.annotation.NonNull; -import code.name.monkey.retromusic.loaders.PlaylistSongsLoader; + import java.util.ArrayList; +import code.name.monkey.retromusic.loaders.PlaylistSongsLoader; + public class Playlist implements Parcelable { diff --git a/app/src/main/java/code/name/monkey/retromusic/model/PlaylistSong.java b/app/src/main/java/code/name/monkey/retromusic/model/PlaylistSong.java index c1bd50b9..01b335bf 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/PlaylistSong.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/PlaylistSong.java @@ -14,9 +14,10 @@ package code.name.monkey.retromusic.model; -import kotlinx.android.parcel.Parcelize; import org.jetbrains.annotations.NotNull; +import kotlinx.android.parcel.Parcelize; + /** * Created by hemanths on 3/4/19 */ @@ -28,19 +29,19 @@ public class PlaylistSong extends Song { final int playlistId; public PlaylistSong(int id, - @NotNull String title, - int trackNumber, - int year, - long duration, - @NotNull String data, - long dateModified, - int albumId, - @NotNull String albumName, - int artistId, - @NotNull String artistName, - int playlistId, - int idInPlayList, - @NotNull String composer) { + @NotNull String title, + int trackNumber, + int year, + long duration, + @NotNull String data, + long dateModified, + int albumId, + @NotNull String albumName, + int artistId, + @NotNull String artistName, + int playlistId, + int idInPlayList, + @NotNull String composer) { super(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName, composer); this.playlistId = playlistId; diff --git a/app/src/main/java/code/name/monkey/retromusic/model/lyrics/Lyrics.java b/app/src/main/java/code/name/monkey/retromusic/model/lyrics/Lyrics.java index f3efe92d..32bbfd4a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/lyrics/Lyrics.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/lyrics/Lyrics.java @@ -15,19 +15,21 @@ package code.name.monkey.retromusic.model.lyrics; -import code.name.monkey.retromusic.model.Song; import java.util.ArrayList; +import code.name.monkey.retromusic.model.Song; + public class Lyrics { private static final ArrayList> FORMATS = new ArrayList<>(); + static { + Lyrics.FORMATS.add(SynchronizedLyricsLRC.class); + } + public String data; - public Song song; - protected boolean parsed = false; - protected boolean valid = false; public static boolean isSynchronized(String data) { @@ -82,8 +84,4 @@ public class Lyrics { this.data = data; return this; } - - static { - Lyrics.FORMATS.add(SynchronizedLyricsLRC.class); - } } diff --git a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/AbsSmartPlaylist.java b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/AbsSmartPlaylist.java index 12d00acb..0e7338cc 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/AbsSmartPlaylist.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/AbsSmartPlaylist.java @@ -16,8 +16,10 @@ package code.name.monkey.retromusic.model.smartplaylist; import android.content.Context; import android.os.Parcel; + import androidx.annotation.DrawableRes; import androidx.annotation.Nullable; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.model.AbsCustomPlaylist; diff --git a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/HistoryPlaylist.java b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/HistoryPlaylist.java index a7f47a5d..5e5cf7b1 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/HistoryPlaylist.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/HistoryPlaylist.java @@ -16,13 +16,17 @@ package code.name.monkey.retromusic.model.smartplaylist; import android.content.Context; import android.os.Parcel; + import androidx.annotation.NonNull; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader; import code.name.monkey.retromusic.model.Song; import code.name.monkey.retromusic.providers.HistoryStore; -import java.util.ArrayList; -import org.jetbrains.annotations.NotNull; /** * @author Karim Abou Zeid (kabouzeid) diff --git a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/LastAddedPlaylist.java b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/LastAddedPlaylist.java index 2d716212..08371a00 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/LastAddedPlaylist.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/LastAddedPlaylist.java @@ -16,12 +16,16 @@ package code.name.monkey.retromusic.model.smartplaylist; import android.content.Context; import android.os.Parcel; + import androidx.annotation.NonNull; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.loaders.LastAddedSongsLoader; import code.name.monkey.retromusic.model.Song; -import java.util.ArrayList; -import org.jetbrains.annotations.NotNull; public class LastAddedPlaylist extends AbsSmartPlaylist { diff --git a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/MyTopTracksPlaylist.java b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/MyTopTracksPlaylist.java index 7a1346c0..5bff552a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/MyTopTracksPlaylist.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/MyTopTracksPlaylist.java @@ -16,13 +16,17 @@ package code.name.monkey.retromusic.model.smartplaylist; import android.content.Context; import android.os.Parcel; + import androidx.annotation.NonNull; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader; import code.name.monkey.retromusic.model.Song; import code.name.monkey.retromusic.providers.SongPlayCountStore; -import java.util.ArrayList; -import org.jetbrains.annotations.NotNull; /** * @author Karim Abou Zeid (kabouzeid) diff --git a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/ShuffleAllPlaylist.java b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/ShuffleAllPlaylist.java index e3133212..8c26b7af 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/ShuffleAllPlaylist.java +++ b/app/src/main/java/code/name/monkey/retromusic/model/smartplaylist/ShuffleAllPlaylist.java @@ -16,12 +16,16 @@ package code.name.monkey.retromusic.model.smartplaylist; import android.content.Context; import android.os.Parcel; + import androidx.annotation.NonNull; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.loaders.SongLoader; import code.name.monkey.retromusic.model.Song; -import java.util.ArrayList; -import org.jetbrains.annotations.NotNull; public class ShuffleAllPlaylist extends AbsSmartPlaylist { diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumDetailsPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumDetailsPresenter.kt index d6fde1bb..8b53f370 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumDetailsPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumDetailsPresenter.kt @@ -21,11 +21,7 @@ import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository import code.name.monkey.retromusic.rest.model.LastFmAlbum -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumPresenter.kt index e0b632b9..936fd44b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/AlbumPresenter.kt @@ -21,11 +21,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistDetailsPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistDetailsPresenter.kt index 888114b6..649df094 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistDetailsPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistDetailsPresenter.kt @@ -22,12 +22,8 @@ import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository import code.name.monkey.retromusic.rest.model.LastFmArtist -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import java.util.Locale +import kotlinx.coroutines.* +import java.util.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistPresenter.kt index d78e12d6..42a941da 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/ArtistPresenter.kt @@ -21,11 +21,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenreDetailsPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenreDetailsPresenter.kt index 5469ddf9..ed664155 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenreDetailsPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenreDetailsPresenter.kt @@ -21,11 +21,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenrePresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenrePresenter.kt index 62d2474c..50f0722c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenrePresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/GenrePresenter.kt @@ -21,11 +21,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/HomePresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/HomePresenter.kt index 1d1f81a9..1bdf66e9 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/HomePresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/HomePresenter.kt @@ -20,11 +20,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistPresenter.kt index 2767dc44..dcd8d921 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistPresenter.kt @@ -20,11 +20,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistSongsPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistSongsPresenter.kt index 20b43388..d02bc52a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistSongsPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/PlaylistSongsPresenter.kt @@ -22,11 +22,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SearchPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SearchPresenter.kt index d920bb90..b371cb7b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SearchPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SearchPresenter.kt @@ -20,11 +20,7 @@ import code.name.monkey.retromusic.mvp.BaseView import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SongPresenter.kt b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SongPresenter.kt index bf076302..ceb6b45c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SongPresenter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/mvp/presenter/SongPresenter.kt @@ -19,11 +19,7 @@ import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.mvp.Presenter import code.name.monkey.retromusic.mvp.PresenterImpl import code.name.monkey.retromusic.providers.interfaces.Repository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import javax.inject.Inject import kotlin.coroutines.CoroutineContext diff --git a/app/src/main/java/code/name/monkey/retromusic/preferences/AlbumCoverStylePreferenceDialog.kt b/app/src/main/java/code/name/monkey/retromusic/preferences/AlbumCoverStylePreferenceDialog.kt index 900404b0..89592f28 100644 --- a/app/src/main/java/code/name/monkey/retromusic/preferences/AlbumCoverStylePreferenceDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/preferences/AlbumCoverStylePreferenceDialog.kt @@ -35,10 +35,7 @@ import code.name.monkey.retromusic.App import code.name.monkey.retromusic.R import code.name.monkey.retromusic.extensions.colorControlNormal import code.name.monkey.retromusic.fragments.AlbumCoverStyle -import code.name.monkey.retromusic.fragments.AlbumCoverStyle.CARD -import code.name.monkey.retromusic.fragments.AlbumCoverStyle.CIRCLE -import code.name.monkey.retromusic.fragments.AlbumCoverStyle.FULL_CARD -import code.name.monkey.retromusic.fragments.AlbumCoverStyle.values +import code.name.monkey.retromusic.fragments.AlbumCoverStyle.* import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.ViewUtil @@ -61,11 +58,15 @@ class AlbumCoverStylePreference @JvmOverloads constructor( init { icon?.colorFilter = - BlendModeColorFilterCompat.createBlendModeColorFilterCompat(colorControlNormal(context), SRC_IN) + BlendModeColorFilterCompat.createBlendModeColorFilterCompat( + colorControlNormal(context), + SRC_IN + ) } } -class AlbumCoverStylePreferenceDialog : PreferenceDialogFragmentCompat(), ViewPager.OnPageChangeListener { +class AlbumCoverStylePreferenceDialog : PreferenceDialogFragmentCompat(), + ViewPager.OnPageChangeListener { override fun onDialogClosed(positiveResult: Boolean) { } @@ -73,7 +74,8 @@ class AlbumCoverStylePreferenceDialog : PreferenceDialogFragmentCompat(), ViewPa override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { @SuppressLint("InflateParams") val view = - LayoutInflater.from(activity).inflate(R.layout.preference_dialog_now_playing_screen, null) + LayoutInflater.from(activity) + .inflate(R.layout.preference_dialog_now_playing_screen, null) val viewPager = view.findViewById(R.id.now_playing_screen_view_pager) viewPager.adapter = AlbumCoverStyleAdapter(activity!!) viewPager.addOnPageChangeListener(this) @@ -109,13 +111,18 @@ class AlbumCoverStylePreferenceDialog : PreferenceDialogFragmentCompat(), ViewPa override fun onPageScrollStateChanged(state: Int) { } - private class AlbumCoverStyleAdapter internal constructor(private val context: Context) : PagerAdapter() { + private class AlbumCoverStyleAdapter internal constructor(private val context: Context) : + PagerAdapter() { override fun instantiateItem(collection: ViewGroup, position: Int): Any { val albumCoverStyle = values()[position] val inflater = LayoutInflater.from(context) - val layout = inflater.inflate(R.layout.preference_now_playing_screen_item, collection, false) as ViewGroup + val layout = inflater.inflate( + R.layout.preference_now_playing_screen_item, + collection, + false + ) as ViewGroup collection.addView(layout) val image = layout.findViewById(R.id.image) diff --git a/app/src/main/java/code/name/monkey/retromusic/preferences/BlacklistPreferenceDialog.kt b/app/src/main/java/code/name/monkey/retromusic/preferences/BlacklistPreferenceDialog.kt index 1d4fab50..e0681d61 100644 --- a/app/src/main/java/code/name/monkey/retromusic/preferences/BlacklistPreferenceDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/preferences/BlacklistPreferenceDialog.kt @@ -33,7 +33,7 @@ import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.bottomsheets.BottomSheet import com.afollestad.materialdialogs.list.listItems import java.io.File -import java.util.ArrayList +import java.util.* class BlacklistPreference @JvmOverloads constructor( context: Context, @@ -44,7 +44,10 @@ class BlacklistPreference @JvmOverloads constructor( init { icon?.colorFilter = - BlendModeColorFilterCompat.createBlendModeColorFilterCompat(colorControlNormal(context), SRC_IN) + BlendModeColorFilterCompat.createBlendModeColorFilterCompat( + colorControlNormal(context), + SRC_IN + ) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/preferences/LibraryPreference.kt b/app/src/main/java/code/name/monkey/retromusic/preferences/LibraryPreference.kt index b07aa0a5..cec2e2f6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/preferences/LibraryPreference.kt +++ b/app/src/main/java/code/name/monkey/retromusic/preferences/LibraryPreference.kt @@ -34,7 +34,7 @@ import com.afollestad.materialdialogs.LayoutMode import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.bottomsheets.BottomSheet import com.afollestad.materialdialogs.customview.customView -import java.util.ArrayList +import java.util.* class LibraryPreference @JvmOverloads constructor( context: Context, @@ -46,7 +46,10 @@ class LibraryPreference @JvmOverloads constructor( init { icon?.colorFilter = - BlendModeColorFilterCompat.createBlendModeColorFilterCompat(colorControlNormal(context), SRC_IN) + BlendModeColorFilterCompat.createBlendModeColorFilterCompat( + colorControlNormal(context), + SRC_IN + ) } } @@ -58,7 +61,10 @@ class LibraryPreferenceDialog : PreferenceDialogFragmentCompat() { lateinit var adapter: CategoryInfoAdapter override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val view = requireActivity().layoutInflater.inflate(R.layout.preference_dialog_library_categories, null) + val view = requireActivity().layoutInflater.inflate( + R.layout.preference_dialog_library_categories, + null + ) val categoryInfos: List = if (savedInstanceState != null) { savedInstanceState.getParcelableArrayList(PreferenceUtil.LIBRARY_CATEGORIES)!! @@ -85,14 +91,18 @@ class LibraryPreferenceDialog : PreferenceDialogFragmentCompat() { dismiss() } .neutralButton(R.string.reset_action) { - adapter.categoryInfos = PreferenceUtil.getInstance(requireContext()).defaultLibraryCategoryInfos + adapter.categoryInfos = + PreferenceUtil.getInstance(requireContext()).defaultLibraryCategoryInfos } .noAutoDismiss() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - outState.putParcelableArrayList(PreferenceUtil.LIBRARY_CATEGORIES, ArrayList(adapter.categoryInfos)) + outState.putParcelableArrayList( + PreferenceUtil.LIBRARY_CATEGORIES, + ArrayList(adapter.categoryInfos) + ) } private fun updateCategories(categories: List) { diff --git a/app/src/main/java/code/name/monkey/retromusic/preferences/NowPlayingScreenPreferenceDialog.kt b/app/src/main/java/code/name/monkey/retromusic/preferences/NowPlayingScreenPreferenceDialog.kt index 1eb98ce5..2ef3b5af 100644 --- a/app/src/main/java/code/name/monkey/retromusic/preferences/NowPlayingScreenPreferenceDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/preferences/NowPlayingScreenPreferenceDialog.kt @@ -34,16 +34,7 @@ import code.name.monkey.retromusic.App import code.name.monkey.retromusic.R import code.name.monkey.retromusic.extensions.colorControlNormal import code.name.monkey.retromusic.fragments.NowPlayingScreen -import code.name.monkey.retromusic.fragments.NowPlayingScreen.ADAPTIVE -import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR -import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR_CARD -import code.name.monkey.retromusic.fragments.NowPlayingScreen.CARD -import code.name.monkey.retromusic.fragments.NowPlayingScreen.CIRCLE -import code.name.monkey.retromusic.fragments.NowPlayingScreen.COLOR -import code.name.monkey.retromusic.fragments.NowPlayingScreen.FULL -import code.name.monkey.retromusic.fragments.NowPlayingScreen.PLAIN -import code.name.monkey.retromusic.fragments.NowPlayingScreen.SIMPLE -import code.name.monkey.retromusic.fragments.NowPlayingScreen.values +import code.name.monkey.retromusic.fragments.NowPlayingScreen.* import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.ViewUtil @@ -72,7 +63,8 @@ class NowPlayingScreenPreference @JvmOverloads constructor( } } -class NowPlayingScreenPreferenceDialog : PreferenceDialogFragmentCompat(), ViewPager.OnPageChangeListener { +class NowPlayingScreenPreferenceDialog : PreferenceDialogFragmentCompat(), + ViewPager.OnPageChangeListener { private var viewPagerPosition: Int = 0 @@ -90,13 +82,15 @@ class NowPlayingScreenPreferenceDialog : PreferenceDialogFragmentCompat(), ViewP } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val view = LayoutInflater.from(activity).inflate(R.layout.preference_dialog_now_playing_screen, null) + val view = LayoutInflater.from(activity) + .inflate(R.layout.preference_dialog_now_playing_screen, null) val viewPager = view.findViewById(R.id.now_playing_screen_view_pager) ?: throw IllegalStateException("Dialog view must contain a ViewPager with id 'now_playing_screen_view_pager'") viewPager.adapter = NowPlayingScreenAdapter(requireContext()) viewPager.addOnPageChangeListener(this) viewPager.pageMargin = ViewUtil.convertDpToPixel(32f, resources).toInt() - viewPager.currentItem = PreferenceUtil.getInstance(requireContext()).nowPlayingScreen.ordinal + viewPager.currentItem = + PreferenceUtil.getInstance(requireContext()).nowPlayingScreen.ordinal return MaterialDialog(requireContext()).show { @@ -104,7 +98,8 @@ class NowPlayingScreenPreferenceDialog : PreferenceDialogFragmentCompat(), ViewP positiveButton(R.string.set) { val nowPlayingScreen = values()[viewPagerPosition] if (isNowPlayingThemes(nowPlayingScreen)) { - val result = getString(nowPlayingScreen.titleRes) + " theme is Pro version feature." + val result = + getString(nowPlayingScreen.titleRes) + " theme is Pro version feature." Toast.makeText(context, result, Toast.LENGTH_SHORT).show() NavigationUtil.goToProVersion(activity!!) } else { @@ -134,7 +129,11 @@ private class NowPlayingScreenAdapter(private val context: Context) : PagerAdapt val nowPlayingScreen = values()[position] val inflater = LayoutInflater.from(context) - val layout = inflater.inflate(R.layout.preference_now_playing_screen_item, collection, false) as ViewGroup + val layout = inflater.inflate( + R.layout.preference_now_playing_screen_item, + collection, + false + ) as ViewGroup collection.addView(layout) val image = layout.findViewById(R.id.image) diff --git a/app/src/main/java/code/name/monkey/retromusic/providers/HistoryStore.java b/app/src/main/java/code/name/monkey/retromusic/providers/HistoryStore.java index c6708f44..0e283f3d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/providers/HistoryStore.java +++ b/app/src/main/java/code/name/monkey/retromusic/providers/HistoryStore.java @@ -19,6 +19,7 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/app/src/main/java/code/name/monkey/retromusic/providers/MusicPlaybackQueueStore.java b/app/src/main/java/code/name/monkey/retromusic/providers/MusicPlaybackQueueStore.java index 935d2689..528ca7e9 100644 --- a/app/src/main/java/code/name/monkey/retromusic/providers/MusicPlaybackQueueStore.java +++ b/app/src/main/java/code/name/monkey/retromusic/providers/MusicPlaybackQueueStore.java @@ -20,11 +20,14 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.provider.BaseColumns; import android.provider.MediaStore.Audio.AudioColumns; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; + +import java.util.ArrayList; + import code.name.monkey.retromusic.loaders.SongLoader; import code.name.monkey.retromusic.model.Song; -import java.util.ArrayList; /** * @author Andrew Neal, modified for Phonograph by Karim Abou Zeid @@ -44,6 +47,15 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper { @Nullable private static MusicPlaybackQueueStore sInstance = null; + /** + * Constructor of MusicPlaybackState + * + * @param context The {@link Context} to use + */ + public MusicPlaybackQueueStore(final @NonNull Context context) { + super(context, DATABASE_NAME, null, VERSION); + } + /** * @param context The {@link Context} to use * @return A new instance of this class. @@ -56,15 +68,6 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper { return sInstance; } - /** - * Constructor of MusicPlaybackState - * - * @param context The {@link Context} to use - */ - public MusicPlaybackQueueStore(final @NonNull Context context) { - super(context, DATABASE_NAME, null, VERSION); - } - @Override public void onCreate(@NonNull final SQLiteDatabase db) { createTable(db, PLAYING_QUEUE_TABLE_NAME); @@ -98,7 +101,7 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper { } public synchronized void saveQueues(@NonNull final ArrayList playingQueue, - @NonNull final ArrayList originalPlayingQueue) { + @NonNull final ArrayList originalPlayingQueue) { saveQueue(PLAYING_QUEUE_TABLE_NAME, playingQueue); saveQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME, originalPlayingQueue); } diff --git a/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt b/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt index 20a1b3b3..91d4f947 100644 --- a/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt +++ b/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt @@ -20,22 +20,8 @@ import code.name.monkey.retromusic.Result import code.name.monkey.retromusic.Result.Error import code.name.monkey.retromusic.Result.Success import code.name.monkey.retromusic.adapter.HomeAdapter -import code.name.monkey.retromusic.loaders.AlbumLoader -import code.name.monkey.retromusic.loaders.ArtistLoader -import code.name.monkey.retromusic.loaders.GenreLoader -import code.name.monkey.retromusic.loaders.LastAddedSongsLoader -import code.name.monkey.retromusic.loaders.PlaylistLoader -import code.name.monkey.retromusic.loaders.PlaylistSongsLoader -import code.name.monkey.retromusic.loaders.SearchLoader -import code.name.monkey.retromusic.loaders.SongLoader -import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader -import code.name.monkey.retromusic.model.AbsCustomPlaylist -import code.name.monkey.retromusic.model.Album -import code.name.monkey.retromusic.model.Artist -import code.name.monkey.retromusic.model.Genre -import code.name.monkey.retromusic.model.Home -import code.name.monkey.retromusic.model.Playlist -import code.name.monkey.retromusic.model.Song +import code.name.monkey.retromusic.loaders.* +import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.providers.interfaces.Repository import code.name.monkey.retromusic.rest.LastFMRestClient import code.name.monkey.retromusic.rest.model.LastFmAlbum @@ -299,8 +285,9 @@ class RepositoryImpl @Inject constructor(private val context: Context) : Reposit } } -suspend fun safeApiCall(call: suspend () -> Result, errorMessage: String): Result = try { - call.invoke() -} catch (e: Exception) { - Error(IOException(errorMessage, e)) -} +suspend fun safeApiCall(call: suspend () -> Result, errorMessage: String): Result = + try { + call.invoke() + } catch (e: Exception) { + Error(IOException(errorMessage, e)) + } diff --git a/app/src/main/java/code/name/monkey/retromusic/providers/interfaces/Repository.kt b/app/src/main/java/code/name/monkey/retromusic/providers/interfaces/Repository.kt index aec8eaea..a3e9f4d8 100644 --- a/app/src/main/java/code/name/monkey/retromusic/providers/interfaces/Repository.kt +++ b/app/src/main/java/code/name/monkey/retromusic/providers/interfaces/Repository.kt @@ -15,12 +15,7 @@ package code.name.monkey.retromusic.providers.interfaces import code.name.monkey.retromusic.Result -import code.name.monkey.retromusic.model.Album -import code.name.monkey.retromusic.model.Artist -import code.name.monkey.retromusic.model.Genre -import code.name.monkey.retromusic.model.Home -import code.name.monkey.retromusic.model.Playlist -import code.name.monkey.retromusic.model.Song +import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.rest.model.LastFmAlbum import code.name.monkey.retromusic.rest.model.LastFmArtist diff --git a/app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java b/app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java index d5c67f09..8e1113ea 100644 --- a/app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java +++ b/app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java @@ -15,11 +15,14 @@ package code.name.monkey.retromusic.rest; import android.content.Context; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import code.name.monkey.retromusic.rest.service.LastFMService; + import java.io.File; import java.util.concurrent.TimeUnit; + +import code.name.monkey.retromusic.rest.service.LastFMService; import okhttp3.Cache; import okhttp3.Call; import okhttp3.ConnectionPool; @@ -51,11 +54,6 @@ public class LastFMRestClient { apiService = restAdapter.create(LastFMService.class); } - @NonNull - public LastFMService getApiService() { - return apiService; - } - private static Interceptor createCacheControlInterceptor() { return chain -> { Request modifiedRequest = chain.request().newBuilder() @@ -93,4 +91,9 @@ public class LastFMRestClient { interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); return interceptor; } + + @NonNull + public LastFMService getApiService() { + return apiService; + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmAlbum.java b/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmAlbum.java index ae4da518..7c3ca35e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmAlbum.java +++ b/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmAlbum.java @@ -16,13 +16,82 @@ package code.name.monkey.retromusic.rest.model; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; + import java.util.ArrayList; import java.util.List; public class LastFmAlbum { + @Expose + private Album album; + + public Album getAlbum() { + return album; + } + + public void setAlbum(Album album) { + this.album = album; + } + public static class Album { + @Expose + public String listeners; + @Expose + public String playcount; + @Expose + private List image = new ArrayList<>(); + @Expose + private String name; + @Expose + private Tags tags; + @Expose + private Wiki wiki; + + public List getImage() { + return image; + } + + public void setImage(List image) { + this.image = image; + } + + public String getListeners() { + return listeners; + } + + public void setListeners(final String listeners) { + this.listeners = listeners; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getPlaycount() { + return playcount; + } + + public void setPlaycount(final String playcount) { + this.playcount = playcount; + } + + public Tags getTags() { + return tags; + } + + public Wiki getWiki() { + return wiki; + } + + public void setWiki(Wiki wiki) { + this.wiki = wiki; + } + public static class Image { @SerializedName("#text") @@ -100,78 +169,5 @@ public class LastFmAlbum { this.published = published; } } - - @Expose - public String listeners; - - @Expose - public String playcount; - - @Expose - private List image = new ArrayList<>(); - - @Expose - private String name; - - @Expose - private Tags tags; - - @Expose - private Wiki wiki; - - public List getImage() { - return image; - } - - public void setImage(List image) { - this.image = image; - } - - public String getListeners() { - return listeners; - } - - public void setListeners(final String listeners) { - this.listeners = listeners; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public String getPlaycount() { - return playcount; - } - - public void setPlaycount(final String playcount) { - this.playcount = playcount; - } - - public Tags getTags() { - return tags; - } - - public Wiki getWiki() { - return wiki; - } - - public void setWiki(Wiki wiki) { - this.wiki = wiki; - } - } - - @Expose - private Album album; - - public Album getAlbum() { - return album; - } - - public void setAlbum(Album album) { - this.album = album; } } diff --git a/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmArtist.java b/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmArtist.java index 4afc19cd..84de1182 100644 --- a/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmArtist.java +++ b/app/src/main/java/code/name/monkey/retromusic/rest/model/LastFmArtist.java @@ -16,13 +16,48 @@ package code.name.monkey.retromusic.rest.model; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; + import java.util.ArrayList; import java.util.List; public class LastFmArtist { + @Expose + private Artist artist; + + public Artist getArtist() { + return artist; + } + + public void setArtist(Artist artist) { + this.artist = artist; + } + public static class Artist { + @Expose + public Stats stats; + @Expose + private Bio bio; + @Expose + private List image = new ArrayList<>(); + + public Bio getBio() { + return bio; + } + + public void setBio(Bio bio) { + this.bio = bio; + } + + public List getImage() { + return image; + } + + public void setImage(List image) { + this.image = image; + } + public static class Image { @SerializedName("#text") @@ -87,41 +122,5 @@ public class LastFmArtist { this.content = content; } } - - @Expose - public Stats stats; - - @Expose - private Bio bio; - - @Expose - private List image = new ArrayList<>(); - - public Bio getBio() { - return bio; - } - - public void setBio(Bio bio) { - this.bio = bio; - } - - public List getImage() { - return image; - } - - public void setImage(List image) { - this.image = image; - } - } - - @Expose - private Artist artist; - - public Artist getArtist() { - return artist; - } - - public void setArtist(Artist artist) { - this.artist = artist; } } diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MediaButtonIntentReceiver.kt b/app/src/main/java/code/name/monkey/retromusic/service/MediaButtonIntentReceiver.kt index 09c282a7..d77a7d75 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MediaButtonIntentReceiver.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/MediaButtonIntentReceiver.kt @@ -87,7 +87,7 @@ class MediaButtonIntentReceiver : BroadcastReceiver() { val intentAction = intent.action if (Intent.ACTION_MEDIA_BUTTON == intentAction) { val event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT) - ?: return false + ?: return false val keycode = event.keyCode val action = event.action @@ -99,7 +99,8 @@ class MediaButtonIntentReceiver : BroadcastReceiver() { var command: String? = null when (keycode) { KeyEvent.KEYCODE_MEDIA_STOP -> command = ACTION_STOP - KeyEvent.KEYCODE_HEADSETHOOK, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> command = ACTION_TOGGLE_PAUSE + KeyEvent.KEYCODE_HEADSETHOOK, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> command = + ACTION_TOGGLE_PAUSE KeyEvent.KEYCODE_MEDIA_NEXT -> command = ACTION_SKIP KeyEvent.KEYCODE_MEDIA_PREVIOUS -> command = ACTION_REWIND KeyEvent.KEYCODE_MEDIA_PAUSE -> command = ACTION_PAUSE @@ -125,7 +126,8 @@ class MediaButtonIntentReceiver : BroadcastReceiver() { mHandler.removeMessages(MSG_HEADSET_DOUBLE_CLICK_TIMEOUT) val msg = mHandler.obtainMessage( - MSG_HEADSET_DOUBLE_CLICK_TIMEOUT, mClickCounter, 0, context) + MSG_HEADSET_DOUBLE_CLICK_TIMEOUT, mClickCounter, 0, context + ) val delay = (if (mClickCounter < 3) DOUBLE_CLICK else 0).toLong() if (mClickCounter >= 3) { @@ -164,7 +166,10 @@ class MediaButtonIntentReceiver : BroadcastReceiver() { if (wakeLock == null) { val appContext = context.applicationContext val pm = appContext.getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "RetroMusicApp:Wakelock headset button") + wakeLock = pm.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, + "RetroMusicApp:Wakelock headset button" + ) wakeLock!!.setReferenceCounted(false) } if (DEBUG) Log.v(TAG, "Acquiring wake lock and sending " + msg.what) diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MediaSessionCallback.kt b/app/src/main/java/code/name/monkey/retromusic/service/MediaSessionCallback.kt index ce823ffe..00ed323b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MediaSessionCallback.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/MediaSessionCallback.kt @@ -30,8 +30,9 @@ import java.util.* * Created by hemanths on 2019-08-01. */ -class MediaSessionCallback(private val context: Context, - private val musicService: MusicService +class MediaSessionCallback( + private val context: Context, + private val musicService: MusicService ) : MediaSessionCompat.Callback() { override fun onPlay() { diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MediaStoreObserver.kt b/app/src/main/java/code/name/monkey/retromusic/service/MediaStoreObserver.kt index 5aad0f00..27a6c3cc 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MediaStoreObserver.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/MediaStoreObserver.kt @@ -18,8 +18,8 @@ import android.database.ContentObserver import android.os.Handler class MediaStoreObserver( - private val musicService: MusicService, - private val mHandler: Handler + private val musicService: MusicService, + private val mHandler: Handler ) : ContentObserver(mHandler), Runnable { override fun onChange(selfChange: Boolean) { diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java b/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java index d8ecf574..9bc0078e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java +++ b/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java @@ -21,11 +21,12 @@ import android.media.MediaPlayer; import android.media.audiofx.AudioEffect; import android.net.Uri; import android.os.PowerManager; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.util.Log; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.service.playback.Playback; import code.name.monkey.retromusic.util.PreferenceUtil; diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java index 9218131d..148ff5e7 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java +++ b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java @@ -47,9 +47,21 @@ import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.PreferenceManager; + +import com.bumptech.glide.BitmapRequestBuilder; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.animation.GlideAnimation; +import com.bumptech.glide.request.target.SimpleTarget; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Random; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.appwidgets.AppWidgetBig; import code.name.monkey.retromusic.appwidgets.AppWidgetCard; @@ -71,14 +83,6 @@ import code.name.monkey.retromusic.service.playback.Playback; import code.name.monkey.retromusic.util.MusicUtil; import code.name.monkey.retromusic.util.PreferenceUtil; import code.name.monkey.retromusic.util.RetroUtil; -import com.bumptech.glide.BitmapRequestBuilder; -import com.bumptech.glide.Glide; -import com.bumptech.glide.request.animation.GlideAnimation; -import com.bumptech.glide.request.target.SimpleTarget; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Random; /** * @author Karim Abou Zeid (kabouzeid), Andrew Neal @@ -86,107 +90,53 @@ import java.util.Random; public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks { - public class MusicBinder extends Binder { - - @NonNull - public MusicService getService() { - return MusicService.this; - } - } - public static final String TAG = MusicService.class.getSimpleName(); - public static final String RETRO_MUSIC_PACKAGE_NAME = "code.name.monkey.retromusic"; - public static final String MUSIC_PACKAGE_NAME = "com.android.music"; - public static final String ACTION_TOGGLE_PAUSE = RETRO_MUSIC_PACKAGE_NAME + ".togglepause"; - public static final String ACTION_PLAY = RETRO_MUSIC_PACKAGE_NAME + ".play"; - public static final String ACTION_PLAY_PLAYLIST = RETRO_MUSIC_PACKAGE_NAME + ".play.playlist"; - public static final String ACTION_PAUSE = RETRO_MUSIC_PACKAGE_NAME + ".pause"; - public static final String ACTION_STOP = RETRO_MUSIC_PACKAGE_NAME + ".stop"; - public static final String ACTION_SKIP = RETRO_MUSIC_PACKAGE_NAME + ".skip"; - public static final String ACTION_REWIND = RETRO_MUSIC_PACKAGE_NAME + ".rewind"; - public static final String ACTION_QUIT = RETRO_MUSIC_PACKAGE_NAME + ".quitservice"; - public static final String ACTION_PENDING_QUIT = RETRO_MUSIC_PACKAGE_NAME + ".pendingquitservice"; - public static final String INTENT_EXTRA_PLAYLIST = RETRO_MUSIC_PACKAGE_NAME + "intentextra.playlist"; - public static final String INTENT_EXTRA_SHUFFLE_MODE = RETRO_MUSIC_PACKAGE_NAME + ".intentextra.shufflemode"; - public static final String APP_WIDGET_UPDATE = RETRO_MUSIC_PACKAGE_NAME + ".appwidgetupdate"; - public static final String EXTRA_APP_WIDGET_NAME = RETRO_MUSIC_PACKAGE_NAME + "app_widget_name"; - // Do not change these three strings as it will break support with other apps (e.g. last.fm scrobbling) public static final String META_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".metachanged"; - public static final String QUEUE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".queuechanged"; - public static final String PLAY_STATE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".playstatechanged"; - public static final String FAVORITE_STATE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + "favoritestatechanged"; - public static final String REPEAT_MODE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".repeatmodechanged"; - public static final String SHUFFLE_MODE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".shufflemodechanged"; - public static final String MEDIA_STORE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".mediastorechanged"; - public static final String CYCLE_REPEAT = RETRO_MUSIC_PACKAGE_NAME + ".cyclerepeat"; - public static final String TOGGLE_SHUFFLE = RETRO_MUSIC_PACKAGE_NAME + ".toggleshuffle"; - public static final String TOGGLE_FAVORITE = RETRO_MUSIC_PACKAGE_NAME + ".togglefavorite"; - public static final String SAVED_POSITION = "POSITION"; - public static final String SAVED_POSITION_IN_TRACK = "POSITION_IN_TRACK"; - public static final String SAVED_SHUFFLE_MODE = "SHUFFLE_MODE"; - public static final String SAVED_REPEAT_MODE = "REPEAT_MODE"; - public static final int RELEASE_WAKELOCK = 0; - public static final int TRACK_ENDED = 1; - public static final int TRACK_WENT_TO_NEXT = 2; - public static final int PLAY_SONG = 3; - public static final int PREPARE_NEXT = 4; - public static final int SET_POSITION = 5; - public static final int FOCUS_CHANGE = 6; - public static final int DUCK = 7; - public static final int UNDUCK = 8; - public static final int RESTORE_QUEUES = 9; - public static final int SHUFFLE_MODE_NONE = 0; - public static final int SHUFFLE_MODE_SHUFFLE = 1; - public static final int REPEAT_MODE_NONE = 0; - public static final int REPEAT_MODE_ALL = 1; - public static final int REPEAT_MODE_THIS = 2; - public static final int SAVE_QUEUES = 0; - private static final long MEDIA_SESSION_ACTIONS = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE @@ -194,7 +144,7 @@ public class MusicService extends Service implements | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_SEEK_TO; - + private final IBinder musicBind = new MusicBinder(); public int nextPosition = -1; public boolean pendingQuit = false; @@ -213,144 +163,6 @@ public class MusicService extends Service implements private AppWidgetSmall appWidgetSmall = AppWidgetSmall.Companion.getInstance(); private AppWidgetText appWidgetText = AppWidgetText.Companion.getInstance(); - - private AudioManager audioManager; - - private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter( - AudioManager.ACTION_AUDIO_BECOMING_NOISY); - - private boolean becomingNoisyReceiverRegistered; - - private IntentFilter bluetoothConnectedIntentFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED); - - private boolean bluetoothConnectedRegistered = false; - - private IntentFilter headsetReceiverIntentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); - - private boolean headsetReceiverRegistered = false; - - private MediaSessionCompat mediaSession; - - private ContentObserver mediaStoreObserver; - - private final IBinder musicBind = new MusicBinder(); - - private HandlerThread musicPlayerHandlerThread; - - private boolean notHandledMetaChangedForCurrentTrack; - - private ArrayList originalPlayingQueue = new ArrayList<>(); - - private boolean pausedByTransientLossOfFocus; - - private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, @NonNull Intent intent) { - if (intent.getAction() != null && intent.getAction().equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { - pause(); - } - } - }; - - private PlaybackHandler playerHandler; - - private final AudioManager.OnAudioFocusChangeListener audioFocusListener - = new AudioManager.OnAudioFocusChangeListener() { - @Override - public void onAudioFocusChange(final int focusChange) { - playerHandler.obtainMessage(FOCUS_CHANGE, focusChange, 0).sendToTarget(); - } - }; - - private PlayingNotification playingNotification; - - private ArrayList playingQueue = new ArrayList<>(); - - private QueueSaveHandler queueSaveHandler; - - private HandlerThread queueSaveHandlerThread; - - private boolean queuesRestored; - - private int repeatMode; - - private int shuffleMode; - - private SongPlayCountHelper songPlayCountHelper = new SongPlayCountHelper(); - - private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { - @Override - public void onReceive(final Context context, final Intent intent) { - String action = intent.getAction(); - if (action != null) { - if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action) && - PreferenceUtil.getInstance(context).bluetoothSpeaker()) { - if (VERSION.SDK_INT >= VERSION_CODES.M) { - if (getAudioManager().getDevices(AudioManager.GET_DEVICES_OUTPUTS).length > 0) { - play(); - } - } else { - if (getAudioManager().isBluetoothA2dpOn()) { - play(); - } - } - } - } - } - }; - - private PhoneStateListener phoneStateListener = new PhoneStateListener() { - @Override - public void onCallStateChanged(int state, String incomingNumber) { - switch (state) { - case TelephonyManager.CALL_STATE_IDLE: - //Not in call: Play music - play(); - break; - case TelephonyManager.CALL_STATE_RINGING: - case TelephonyManager.CALL_STATE_OFFHOOK: - //A call is dialing, active or on hold - pause(); - break; - default: - } - super.onCallStateChanged(state, incomingNumber); - } - }; - - private BroadcastReceiver headsetReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action != null) { - if (Intent.ACTION_HEADSET_PLUG.equals(action)) { - int state = intent.getIntExtra("state", -1); - switch (state) { - case 0: - pause(); - break; - case 1: - play(); - break; - } - } - } - } - }; - - private ThrottledSeekHandler throttledSeekHandler; - - private Handler uiThreadHandler; - - private final BroadcastReceiver updateFavoriteReceiver = new BroadcastReceiver() { - @Override - public void onReceive(final Context context, final Intent intent) { - updateNotification(); - } - }; - - private PowerManager.WakeLock wakeLock; - private final BroadcastReceiver widgetIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { @@ -383,6 +195,134 @@ public class MusicService extends Service implements } }; + private AudioManager audioManager; + private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter( + AudioManager.ACTION_AUDIO_BECOMING_NOISY); + private boolean becomingNoisyReceiverRegistered; + private IntentFilter bluetoothConnectedIntentFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED); + private boolean bluetoothConnectedRegistered = false; + private IntentFilter headsetReceiverIntentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); + private boolean headsetReceiverRegistered = false; + private MediaSessionCompat mediaSession; + private ContentObserver mediaStoreObserver; + private HandlerThread musicPlayerHandlerThread; + + private boolean notHandledMetaChangedForCurrentTrack; + + private ArrayList originalPlayingQueue = new ArrayList<>(); + + private boolean pausedByTransientLossOfFocus; + + private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, @NonNull Intent intent) { + if (intent.getAction() != null && intent.getAction().equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { + pause(); + } + } + }; + + private PlaybackHandler playerHandler; + + private final AudioManager.OnAudioFocusChangeListener audioFocusListener + = new AudioManager.OnAudioFocusChangeListener() { + @Override + public void onAudioFocusChange(final int focusChange) { + playerHandler.obtainMessage(FOCUS_CHANGE, focusChange, 0).sendToTarget(); + } + }; + + private PlayingNotification playingNotification; + private final BroadcastReceiver updateFavoriteReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + updateNotification(); + } + }; + private ArrayList playingQueue = new ArrayList<>(); + private QueueSaveHandler queueSaveHandler; + private HandlerThread queueSaveHandlerThread; + private boolean queuesRestored; + private int repeatMode; + private int shuffleMode; + private SongPlayCountHelper songPlayCountHelper = new SongPlayCountHelper(); + private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + String action = intent.getAction(); + if (action != null) { + if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action) && + PreferenceUtil.getInstance(context).bluetoothSpeaker()) { + if (VERSION.SDK_INT >= VERSION_CODES.M) { + if (getAudioManager().getDevices(AudioManager.GET_DEVICES_OUTPUTS).length > 0) { + play(); + } + } else { + if (getAudioManager().isBluetoothA2dpOn()) { + play(); + } + } + } + } + } + }; + private PhoneStateListener phoneStateListener = new PhoneStateListener() { + @Override + public void onCallStateChanged(int state, String incomingNumber) { + switch (state) { + case TelephonyManager.CALL_STATE_IDLE: + //Not in call: Play music + play(); + break; + case TelephonyManager.CALL_STATE_RINGING: + case TelephonyManager.CALL_STATE_OFFHOOK: + //A call is dialing, active or on hold + pause(); + break; + default: + } + super.onCallStateChanged(state, incomingNumber); + } + }; + private BroadcastReceiver headsetReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action != null) { + if (Intent.ACTION_HEADSET_PLUG.equals(action)) { + int state = intent.getIntExtra("state", -1); + switch (state) { + case 0: + pause(); + break; + case 1: + play(); + break; + } + } + } + } + }; + private ThrottledSeekHandler throttledSeekHandler; + private Handler uiThreadHandler; + private PowerManager.WakeLock wakeLock; + + private static Bitmap copy(Bitmap bitmap) { + Bitmap.Config config = bitmap.getConfig(); + if (config == null) { + config = Bitmap.Config.RGB_565; + } + try { + return bitmap.copy(config, false); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + return null; + } + } + + private static String getTrackUri(@NonNull Song song) { + return MusicUtil.getSongFileUri(song.getId()).toString(); + } @Override public void onCreate() { @@ -876,7 +816,7 @@ public class MusicService extends Service implements } public void openQueue(@Nullable final List playingQueue, final int startPosition, - final boolean startPlaying) { + final boolean startPlaying) { if (playingQueue != null && !playingQueue.isEmpty() && startPosition >= 0 && startPosition < playingQueue .size()) { // it is important to copy the playing queue here first as we might add/remove songs later @@ -1424,20 +1364,11 @@ public class MusicService extends Service implements } - private static Bitmap copy(Bitmap bitmap) { - Bitmap.Config config = bitmap.getConfig(); - if (config == null) { - config = Bitmap.Config.RGB_565; - } - try { - return bitmap.copy(config, false); - } catch (OutOfMemoryError e) { - e.printStackTrace(); - return null; - } - } + public class MusicBinder extends Binder { - private static String getTrackUri(@NonNull Song song) { - return MusicUtil.getSongFileUri(song.getId()).toString(); + @NonNull + public MusicService getService() { + return MusicService.this; + } } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/service/PlaybackHandler.java b/app/src/main/java/code/name/monkey/retromusic/service/PlaybackHandler.java index 92eed06f..2fe34fbe 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/PlaybackHandler.java +++ b/app/src/main/java/code/name/monkey/retromusic/service/PlaybackHandler.java @@ -14,6 +14,17 @@ package code.name.monkey.retromusic.service; +import android.media.AudioManager; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + +import androidx.annotation.NonNull; + +import java.lang.ref.WeakReference; + +import code.name.monkey.retromusic.util.PreferenceUtil; + import static code.name.monkey.retromusic.service.MusicService.DUCK; import static code.name.monkey.retromusic.service.MusicService.META_CHANGED; import static code.name.monkey.retromusic.service.MusicService.PLAY_STATE_CHANGED; @@ -21,20 +32,11 @@ import static code.name.monkey.retromusic.service.MusicService.REPEAT_MODE_NONE; import static code.name.monkey.retromusic.service.MusicService.TRACK_ENDED; import static code.name.monkey.retromusic.service.MusicService.TRACK_WENT_TO_NEXT; -import android.media.AudioManager; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import androidx.annotation.NonNull; -import code.name.monkey.retromusic.util.PreferenceUtil; -import java.lang.ref.WeakReference; - class PlaybackHandler extends Handler { - private float currentDuckVolume = 1.0f; - @NonNull private final WeakReference mService; + private float currentDuckVolume = 1.0f; PlaybackHandler(final MusicService service, @NonNull final Looper looper) { super(looper); diff --git a/app/src/main/java/code/name/monkey/retromusic/service/QueueSaveHandler.kt b/app/src/main/java/code/name/monkey/retromusic/service/QueueSaveHandler.kt index 44f3eb84..9abc3120 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/QueueSaveHandler.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/QueueSaveHandler.kt @@ -21,8 +21,8 @@ import code.name.monkey.retromusic.service.MusicService.SAVE_QUEUES import java.lang.ref.WeakReference internal class QueueSaveHandler( - musicService: MusicService, - looper: Looper + musicService: MusicService, + looper: Looper ) : Handler(looper) { private val service: WeakReference = WeakReference(musicService) diff --git a/app/src/main/java/code/name/monkey/retromusic/service/ThrottledSeekHandler.kt b/app/src/main/java/code/name/monkey/retromusic/service/ThrottledSeekHandler.kt index 9f2b9fed..71f4cb46 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/ThrottledSeekHandler.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/ThrottledSeekHandler.kt @@ -20,8 +20,8 @@ import android.os.Handler import code.name.monkey.retromusic.service.MusicService.PLAY_STATE_CHANGED class ThrottledSeekHandler( - private val musicService: MusicService, - private val handler: Handler + private val musicService: MusicService, + private val handler: Handler ) : Runnable { fun notifySeek() { diff --git a/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotification.kt b/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotification.kt index 5bb8d56c..4d0476ca 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotification.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotification.kt @@ -73,12 +73,15 @@ abstract class PlayingNotification { @RequiresApi(26) private fun createNotificationChannel() { var notificationChannel: NotificationChannel? = notificationManager!! - .getNotificationChannel(NOTIFICATION_CHANNEL_ID) + .getNotificationChannel(NOTIFICATION_CHANNEL_ID) if (notificationChannel == null) { - notificationChannel = NotificationChannel(NOTIFICATION_CHANNEL_ID, - service.getString(R.string.playing_notification_name), - NotificationManager.IMPORTANCE_LOW) - notificationChannel.description = service.getString(R.string.playing_notification_description) + notificationChannel = NotificationChannel( + NOTIFICATION_CHANNEL_ID, + service.getString(R.string.playing_notification_name), + NotificationManager.IMPORTANCE_LOW + ) + notificationChannel.description = + service.getString(R.string.playing_notification_description) notificationChannel.enableLights(false) notificationChannel.enableVibration(false) notificationChannel.setShowBadge(false) diff --git a/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationImpl.kt b/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationImpl.kt index 47072a8b..f2a95ef5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationImpl.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationImpl.kt @@ -48,13 +48,16 @@ class PlayingNotificationImpl : PlayingNotification() { val song = service.currentSong val isPlaying = service.isPlaying val isFavorite = MusicUtil.isFavorite(service, song) - val playButtonResId = if (isPlaying) R.drawable.ic_pause_white_48dp else R.drawable.ic_play_arrow_white_48dp - val favoriteResId = if (isFavorite) R.drawable.ic_favorite_white_24dp else R.drawable.ic_favorite_border_white_24dp + val playButtonResId = + if (isPlaying) R.drawable.ic_pause_white_48dp else R.drawable.ic_play_arrow_white_48dp + val favoriteResId = + if (isFavorite) R.drawable.ic_favorite_white_24dp else R.drawable.ic_favorite_border_white_24dp val action = Intent(service, MainActivity::class.java) action.putExtra("expand", true) action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - val clickIntent = PendingIntent.getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT) + val clickIntent = + PendingIntent.getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT) val serviceName = ComponentName(service, MusicService::class.java) val intent = Intent(ACTION_QUIT) @@ -62,71 +65,108 @@ class PlayingNotificationImpl : PlayingNotification() { val deleteIntent = PendingIntent.getService(service, 0, intent, 0) val bigNotificationImageSize = service.resources - .getDimensionPixelSize(R.dimen.notification_big_image_size) + .getDimensionPixelSize(R.dimen.notification_big_image_size) service.runOnUiThread { if (target != null) { Glide.clear(target) } target = SongGlideRequest.Builder.from(Glide.with(service), song) - .checkIgnoreMediaStore(service) - .generatePalette(service).build() - .centerCrop() - .into(object : SimpleTarget(bigNotificationImageSize, bigNotificationImageSize) { - override fun onResourceReady(resource: BitmapPaletteWrapper, glideAnimation: GlideAnimation) { - update(resource.bitmap, when { - PreferenceUtil.getInstance(service).isDominantColor -> RetroColorUtil.getDominantColor(resource.bitmap, Color.TRANSPARENT) + .checkIgnoreMediaStore(service) + .generatePalette(service).build() + .centerCrop() + .into(object : SimpleTarget( + bigNotificationImageSize, + bigNotificationImageSize + ) { + override fun onResourceReady( + resource: BitmapPaletteWrapper, + glideAnimation: GlideAnimation + ) { + update( + resource.bitmap, when { + PreferenceUtil.getInstance(service).isDominantColor -> RetroColorUtil.getDominantColor( + resource.bitmap, + Color.TRANSPARENT + ) else -> RetroColorUtil.getColor(resource.palette, Color.TRANSPARENT) - }) + } + ) + } + + override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { + super.onLoadFailed(e, errorDrawable) + update(null, Color.TRANSPARENT) + } + + fun update(bitmap: Bitmap?, color: Int) { + var bitmapFinal = bitmap + if (bitmapFinal == null) { + bitmapFinal = BitmapFactory.decodeResource( + service.resources, + R.drawable.default_audio_art + ) } - override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { - super.onLoadFailed(e, errorDrawable) - update(null, Color.TRANSPARENT) + val toggleFavorite = NotificationCompat.Action( + favoriteResId, + service.getString(R.string.action_toggle_favorite), + retrievePlaybackAction(TOGGLE_FAVORITE) + ) + val playPauseAction = NotificationCompat.Action( + playButtonResId, + service.getString(R.string.action_play_pause), + retrievePlaybackAction(ACTION_TOGGLE_PAUSE) + ) + val previousAction = NotificationCompat.Action( + R.drawable.ic_skip_previous_round_white_32dp, + service.getString(R.string.action_previous), + retrievePlaybackAction(ACTION_REWIND) + ) + val nextAction = NotificationCompat.Action( + R.drawable.ic_skip_next_round_white_32dp, + service.getString(R.string.action_next), + retrievePlaybackAction(ACTION_SKIP) + ) + + val builder = NotificationCompat.Builder( + service, + NOTIFICATION_CHANNEL_ID + ) + .setSmallIcon(R.drawable.ic_notification) + .setLargeIcon(bitmapFinal) + .setContentIntent(clickIntent) + .setDeleteIntent(deleteIntent) + .setContentTitle(Html.fromHtml("" + song.title + "")) + .setContentText(song.artistName) + .setSubText(Html.fromHtml("" + song.albumName + "")) + .setOngoing(isPlaying) + .setShowWhen(false) + .addAction(toggleFavorite) + .addAction(previousAction) + .addAction(playPauseAction) + .addAction(nextAction) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + builder.setStyle( + MediaStyle() + .setMediaSession(service.mediaSession.sessionToken) + .setShowActionsInCompactView(1, 2, 3) + ) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O && PreferenceUtil.getInstance( + service + ).coloredNotification() + ) { + builder.color = color + } } - fun update(bitmap: Bitmap?, color: Int) { - var bitmapFinal = bitmap - if (bitmapFinal == null) { - bitmapFinal = BitmapFactory.decodeResource(service.resources, R.drawable.default_audio_art) - } - - val toggleFavorite = NotificationCompat.Action(favoriteResId, service.getString(R.string.action_toggle_favorite), retrievePlaybackAction(TOGGLE_FAVORITE)) - val playPauseAction = NotificationCompat.Action(playButtonResId, service.getString(R.string.action_play_pause), retrievePlaybackAction(ACTION_TOGGLE_PAUSE)) - val previousAction = NotificationCompat.Action(R.drawable.ic_skip_previous_round_white_32dp, service.getString(R.string.action_previous), retrievePlaybackAction(ACTION_REWIND)) - val nextAction = NotificationCompat.Action(R.drawable.ic_skip_next_round_white_32dp, service.getString(R.string.action_next), retrievePlaybackAction(ACTION_SKIP)) - - val builder = NotificationCompat.Builder(service, - NOTIFICATION_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_notification) - .setLargeIcon(bitmapFinal) - .setContentIntent(clickIntent) - .setDeleteIntent(deleteIntent) - .setContentTitle(Html.fromHtml("" + song.title + "")) - .setContentText(song.artistName) - .setSubText(Html.fromHtml("" + song.albumName + "")) - .setOngoing(isPlaying) - .setShowWhen(false) - .addAction(toggleFavorite) - .addAction(previousAction) - .addAction(playPauseAction) - .addAction(nextAction) - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setStyle(MediaStyle() - .setMediaSession(service.mediaSession.sessionToken) - .setShowActionsInCompactView(1, 2, 3)) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O && PreferenceUtil.getInstance(service).coloredNotification()) { - builder.color = color - } - } - - if (stopped) { - return // notification has been stopped before loading was finished - } - updateNotifyModeAndPostNotification(builder.build()) + if (stopped) { + return // notification has been stopped before loading was finished } - }) + updateNotifyModeAndPostNotification(builder.build()) + } + }) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationOreo.kt b/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationOreo.kt index ebf79e47..39ce02f9 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationOreo.kt +++ b/app/src/main/java/code/name/monkey/retromusic/service/notification/PlayingNotificationOreo.kt @@ -50,8 +50,14 @@ class PlayingNotificationOreo : PlayingNotification() { private var target: Target? = null private fun getCombinedRemoteViews(collapsed: Boolean, song: Song): RemoteViews { - val remoteViews = RemoteViews(service.packageName, if (collapsed) R.layout.layout_notification_collapsed else R.layout.layout_notification_expanded) - remoteViews.setTextViewText(R.id.appName, service.getString(R.string.app_name) + " • " + song.albumName) + val remoteViews = RemoteViews( + service.packageName, + if (collapsed) R.layout.layout_notification_collapsed else R.layout.layout_notification_expanded + ) + remoteViews.setTextViewText( + R.id.appName, + service.getString(R.string.app_name) + " • " + song.albumName + ) remoteViews.setTextViewText(R.id.title, song.title) remoteViews.setTextViewText(R.id.subtitle, song.artistName) linkButtons(remoteViews) @@ -71,103 +77,162 @@ class PlayingNotificationOreo : PlayingNotification() { action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP val clickIntent = PendingIntent - .getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT) + .getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT) val deleteIntent = buildPendingIntent(service, ACTION_QUIT, null) val builder = NotificationCompat.Builder(service, NOTIFICATION_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_notification) - .setContentIntent(clickIntent) - .setDeleteIntent(deleteIntent) - .setCategory(NotificationCompat.CATEGORY_SERVICE) - .setPriority(NotificationCompat.PRIORITY_MAX) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setCustomContentView(notificationLayout) - .setCustomBigContentView(notificationLayoutBig) - .setOngoing(isPlaying) + .setSmallIcon(R.drawable.ic_notification) + .setContentIntent(clickIntent) + .setDeleteIntent(deleteIntent) + .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setCustomContentView(notificationLayout) + .setCustomBigContentView(notificationLayoutBig) + .setOngoing(isPlaying) val bigNotificationImageSize = service.resources - .getDimensionPixelSize(R.dimen.notification_big_image_size) + .getDimensionPixelSize(R.dimen.notification_big_image_size) service.runOnUiThread { if (target != null) { Glide.clear(target) } target = SongGlideRequest.Builder.from(Glide.with(service), song) - .checkIgnoreMediaStore(service) - .generatePalette(service).build() - .centerCrop() - .into(object : SimpleTarget(bigNotificationImageSize, bigNotificationImageSize) { - override fun onResourceReady(resource: BitmapPaletteWrapper, glideAnimation: GlideAnimation) { - val mediaNotificationProcessor = MediaNotificationProcessor(service, service) { i, _ -> update(resource.bitmap, i) } - mediaNotificationProcessor.processNotification(resource.bitmap) + .checkIgnoreMediaStore(service) + .generatePalette(service).build() + .centerCrop() + .into(object : SimpleTarget( + bigNotificationImageSize, + bigNotificationImageSize + ) { + override fun onResourceReady( + resource: BitmapPaletteWrapper, + glideAnimation: GlideAnimation + ) { + val mediaNotificationProcessor = MediaNotificationProcessor( + service, + service + ) { i, _ -> update(resource.bitmap, i) } + mediaNotificationProcessor.processNotification(resource.bitmap) + } + + override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { + super.onLoadFailed(e, errorDrawable) + update( + null, + ATHUtil.resolveColor(service, R.attr.colorSurface, Color.WHITE) + ) + } + + private fun update(bitmap: Bitmap?, bgColor: Int) { + var bgColorFinal = bgColor + if (bitmap != null) { + notificationLayout.setImageViewBitmap(R.id.largeIcon, bitmap) + notificationLayoutBig.setImageViewBitmap(R.id.largeIcon, bitmap) + } else { + notificationLayout.setImageViewResource( + R.id.largeIcon, + R.drawable.default_audio_art + ) + notificationLayoutBig.setImageViewResource( + R.id.largeIcon, + R.drawable.default_audio_art + ) } - override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { - super.onLoadFailed(e, errorDrawable) - update(null, ATHUtil.resolveColor(service, R.attr.colorSurface, Color.WHITE)) + if (!PreferenceUtil.getInstance(service).coloredNotification()) { + bgColorFinal = + ATHUtil.resolveColor(service, R.attr.colorPrimary, Color.WHITE) } + setBackgroundColor(bgColorFinal) + setNotificationContent(ColorUtil.isColorLight(bgColorFinal)) - private fun update(bitmap: Bitmap?, bgColor: Int) { - var bgColorFinal = bgColor - if (bitmap != null) { - notificationLayout.setImageViewBitmap(R.id.largeIcon, bitmap) - notificationLayoutBig.setImageViewBitmap(R.id.largeIcon, bitmap) - } else { - notificationLayout.setImageViewResource(R.id.largeIcon, R.drawable.default_audio_art) - notificationLayoutBig.setImageViewResource(R.id.largeIcon, R.drawable.default_audio_art) - } - - if (!PreferenceUtil.getInstance(service).coloredNotification()) { - bgColorFinal = ATHUtil.resolveColor(service, R.attr.colorPrimary, Color.WHITE) - } - setBackgroundColor(bgColorFinal) - setNotificationContent(ColorUtil.isColorLight(bgColorFinal)) - - if (stopped) { - return // notification has been stopped before loading was finished - } - updateNotifyModeAndPostNotification(builder.build()) + if (stopped) { + return // notification has been stopped before loading was finished } + updateNotifyModeAndPostNotification(builder.build()) + } - private fun setBackgroundColor(color: Int) { - notificationLayout.setInt(R.id.image, "setBackgroundColor", color) - notificationLayoutBig.setInt(R.id.image, "setBackgroundColor", color) - } + private fun setBackgroundColor(color: Int) { + notificationLayout.setInt(R.id.image, "setBackgroundColor", color) + notificationLayoutBig.setInt(R.id.image, "setBackgroundColor", color) + } - private fun setNotificationContent(dark: Boolean) { - val primary = MaterialValueHelper.getPrimaryTextColor(service, dark) - val secondary = MaterialValueHelper.getSecondaryTextColor(service, dark) + private fun setNotificationContent(dark: Boolean) { + val primary = MaterialValueHelper.getPrimaryTextColor(service, dark) + val secondary = MaterialValueHelper.getSecondaryTextColor(service, dark) - val close = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_close_white_24dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER) - val prev = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_round_white_32dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER) - val next = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_round_white_32dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER) - val playPause = createBitmap(RetroUtil.getTintedVectorDrawable(service, - if (isPlaying) - R.drawable.ic_pause_white_48dp - else - R.drawable.ic_play_arrow_white_48dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER) + val close = createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + R.drawable.ic_close_white_24dp, + primary + )!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER + ) + val prev = createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + R.drawable.ic_skip_previous_round_white_32dp, + primary + )!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER + ) + val next = createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + R.drawable.ic_skip_next_round_white_32dp, + primary + )!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER + ) + val playPause = createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + if (isPlaying) + R.drawable.ic_pause_white_48dp + else + R.drawable.ic_play_arrow_white_48dp, primary + )!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER + ) - notificationLayout.setTextColor(R.id.title, primary) - notificationLayout.setTextColor(R.id.subtitle, secondary) - notificationLayout.setTextColor(R.id.appName, secondary) + notificationLayout.setTextColor(R.id.title, primary) + notificationLayout.setTextColor(R.id.subtitle, secondary) + notificationLayout.setTextColor(R.id.appName, secondary) - notificationLayout.setImageViewBitmap(R.id.action_prev, prev) - notificationLayout.setImageViewBitmap(R.id.action_next, next) - notificationLayout.setImageViewBitmap(R.id.action_play_pause, playPause) + notificationLayout.setImageViewBitmap(R.id.action_prev, prev) + notificationLayout.setImageViewBitmap(R.id.action_next, next) + notificationLayout.setImageViewBitmap(R.id.action_play_pause, playPause) - notificationLayoutBig.setTextColor(R.id.title, primary) - notificationLayoutBig.setTextColor(R.id.subtitle, secondary) - notificationLayoutBig.setTextColor(R.id.appName, secondary) + notificationLayoutBig.setTextColor(R.id.title, primary) + notificationLayoutBig.setTextColor(R.id.subtitle, secondary) + notificationLayoutBig.setTextColor(R.id.appName, secondary) - notificationLayoutBig.setImageViewBitmap(R.id.action_quit, close) - notificationLayoutBig.setImageViewBitmap(R.id.action_prev, prev) - notificationLayoutBig.setImageViewBitmap(R.id.action_next, next) - notificationLayoutBig.setImageViewBitmap(R.id.action_play_pause, playPause) + notificationLayoutBig.setImageViewBitmap(R.id.action_quit, close) + notificationLayoutBig.setImageViewBitmap(R.id.action_prev, prev) + notificationLayoutBig.setImageViewBitmap(R.id.action_next, next) + notificationLayoutBig.setImageViewBitmap(R.id.action_play_pause, playPause) - notificationLayout.setImageViewBitmap(R.id.smallIcon, createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_notification, secondary)!!, 0.6f)) - notificationLayoutBig.setImageViewBitmap(R.id.smallIcon, createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_notification, secondary)!!, 0.6f)) + notificationLayout.setImageViewBitmap( + R.id.smallIcon, + createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + R.drawable.ic_notification, + secondary + )!!, 0.6f + ) + ) + notificationLayoutBig.setImageViewBitmap( + R.id.smallIcon, + createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + R.drawable.ic_notification, + secondary + )!!, 0.6f + ) + ) - } - }) + } + }) } if (stopped) { @@ -177,8 +242,10 @@ class PlayingNotificationOreo : PlayingNotification() { } - private fun buildPendingIntent(context: Context, action: String, - serviceName: ComponentName?): PendingIntent { + private fun buildPendingIntent( + context: Context, action: String, + serviceName: ComponentName? + ): PendingIntent { val intent = Intent(action) intent.component = serviceName return PendingIntent.getService(context, 0, intent, 0) diff --git a/app/src/main/java/code/name/monkey/retromusic/transform/ParallaxPagerTransformer.kt b/app/src/main/java/code/name/monkey/retromusic/transform/ParallaxPagerTransformer.kt index 9e5ec9df..ba25df77 100644 --- a/app/src/main/java/code/name/monkey/retromusic/transform/ParallaxPagerTransformer.kt +++ b/app/src/main/java/code/name/monkey/retromusic/transform/ParallaxPagerTransformer.kt @@ -16,7 +16,6 @@ package code.name.monkey.retromusic.transform import android.annotation.TargetApi import android.os.Build -import android.util.Log import android.view.View import androidx.viewpager.widget.ViewPager diff --git a/app/src/main/java/code/name/monkey/retromusic/util/ArtistSignatureUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/ArtistSignatureUtil.java index 6b749345..fece1ea5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/ArtistSignatureUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/ArtistSignatureUtil.java @@ -17,6 +17,7 @@ package code.name.monkey.retromusic.util; import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; + import androidx.annotation.NonNull; import com.bumptech.glide.signature.StringSignature; diff --git a/app/src/main/java/code/name/monkey/retromusic/util/CustomArtistImageUtil.kt b/app/src/main/java/code/name/monkey/retromusic/util/CustomArtistImageUtil.kt index 46dfe37d..a3b221b8 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/CustomArtistImageUtil.kt +++ b/app/src/main/java/code/name/monkey/retromusic/util/CustomArtistImageUtil.kt @@ -33,7 +33,7 @@ import java.io.BufferedOutputStream import java.io.File import java.io.FileOutputStream import java.io.IOException -import java.util.Locale +import java.util.* class CustomArtistImageUtil private constructor(context: Context) { @@ -41,53 +41,65 @@ class CustomArtistImageUtil private constructor(context: Context) { private val mPreferences: SharedPreferences init { - mPreferences = context.applicationContext.getSharedPreferences(CUSTOM_ARTIST_IMAGE_PREFS, Context.MODE_PRIVATE) + mPreferences = context.applicationContext.getSharedPreferences( + CUSTOM_ARTIST_IMAGE_PREFS, + Context.MODE_PRIVATE + ) } fun setCustomArtistImage(artist: Artist, uri: Uri) { Glide.with(App.getContext()) - .load(uri) - .asBitmap() - .diskCacheStrategy(DiskCacheStrategy.NONE) - .skipMemoryCache(true) - .into(object : SimpleTarget() { - override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { - super.onLoadFailed(e, errorDrawable) - e!!.printStackTrace() - Toast.makeText(App.getContext(), e.toString(), Toast.LENGTH_LONG).show() - } + .load(uri) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.NONE) + .skipMemoryCache(true) + .into(object : SimpleTarget() { + override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) { + super.onLoadFailed(e, errorDrawable) + e!!.printStackTrace() + Toast.makeText(App.getContext(), e.toString(), Toast.LENGTH_LONG).show() + } - override fun onResourceReady(resource: Bitmap, glideAnimation: GlideAnimation) { - object : AsyncTask() { - @SuppressLint("ApplySharedPref") - override fun doInBackground(vararg params: Void): Void? { - val dir = File(App.getContext().filesDir, FOLDER_NAME) - if (!dir.exists()) { - if (!dir.mkdirs()) { // create the folder - return null - } + override fun onResourceReady( + resource: Bitmap, + glideAnimation: GlideAnimation + ) { + object : AsyncTask() { + @SuppressLint("ApplySharedPref") + override fun doInBackground(vararg params: Void): Void? { + val dir = File(App.getContext().filesDir, FOLDER_NAME) + if (!dir.exists()) { + if (!dir.mkdirs()) { // create the folder + return null } - val file = File(dir, getFileName(artist)) - - var succesful = false - try { - val os = BufferedOutputStream(FileOutputStream(file)) - succesful = ImageUtil.resizeBitmap(resource, 2048).compress(Bitmap.CompressFormat.JPEG, 100, os) - os.close() - } catch (e: IOException) { - Toast.makeText(App.getContext(), e.toString(), Toast.LENGTH_LONG).show() - } - - if (succesful) { - mPreferences.edit().putBoolean(getFileName(artist), true).commit() - ArtistSignatureUtil.getInstance(App.getContext()).updateArtistSignature(artist.name) - App.getContext().contentResolver.notifyChange(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, null) // trigger media store changed to force artist image reload - } - return null } - }.execute() - } - }) + val file = File(dir, getFileName(artist)) + + var succesful = false + try { + val os = BufferedOutputStream(FileOutputStream(file)) + succesful = ImageUtil.resizeBitmap(resource, 2048) + .compress(Bitmap.CompressFormat.JPEG, 100, os) + os.close() + } catch (e: IOException) { + Toast.makeText(App.getContext(), e.toString(), Toast.LENGTH_LONG) + .show() + } + + if (succesful) { + mPreferences.edit().putBoolean(getFileName(artist), true).commit() + ArtistSignatureUtil.getInstance(App.getContext()) + .updateArtistSignature(artist.name) + App.getContext().contentResolver.notifyChange( + MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, + null + ) // trigger media store changed to force artist image reload + } + return null + } + }.execute() + } + }) } fun resetCustomArtistImage(artist: Artist) { @@ -96,7 +108,10 @@ class CustomArtistImageUtil private constructor(context: Context) { override fun doInBackground(vararg params: Void): Void? { mPreferences.edit().putBoolean(getFileName(artist), false).commit() ArtistSignatureUtil.getInstance(App.getContext()).updateArtistSignature(artist.name) - App.getContext().contentResolver.notifyChange(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, null) // trigger media store changed to force artist image reload + App.getContext().contentResolver.notifyChange( + MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, + null + ) // trigger media store changed to force artist image reload val file = getFile(artist) if (!file.exists()) { diff --git a/app/src/main/java/code/name/monkey/retromusic/util/MusicUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/MusicUtil.java index 440bc6d1..adbd8d5c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/MusicUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/MusicUtil.java @@ -27,9 +27,21 @@ import android.provider.BaseColumns; import android.provider.MediaStore; import android.text.TextUtils; import android.widget.Toast; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.FileProvider; + +import org.jaudiotagger.audio.AudioFileIO; +import org.jaudiotagger.tag.FieldKey; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.regex.Pattern; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.helper.MusicPlayerRemote; import code.name.monkey.retromusic.loaders.PlaylistLoader; @@ -39,14 +51,6 @@ import code.name.monkey.retromusic.model.Playlist; import code.name.monkey.retromusic.model.Song; import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics; import code.name.monkey.retromusic.service.MusicService; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.regex.Pattern; -import org.jaudiotagger.audio.AudioFileIO; -import org.jaudiotagger.tag.FieldKey; public class MusicUtil { @@ -188,7 +192,7 @@ public class MusicUtil { @NonNull public static String getArtistInfoString(@NonNull final Context context, - @NonNull final Artist artist) { + @NonNull final Artist artist) { int albumCount = artist.getAlbumCount(); int songCount = artist.getSongCount(); String albumString = albumCount == 1 ? context.getResources().getString(R.string.album) @@ -379,7 +383,7 @@ public class MusicUtil { } public static boolean isFavoritePlaylist(@NonNull final Context context, - @NonNull final Playlist playlist) { + @NonNull final Playlist playlist) { return playlist.name != null && playlist.name.equals(context.getString(R.string.favorites)); } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/NavigationUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/NavigationUtil.java index 8ce25a27..c6812aeb 100755 --- a/app/src/main/java/code/name/monkey/retromusic/util/NavigationUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/NavigationUtil.java @@ -14,9 +14,6 @@ package code.name.monkey.retromusic.util; -import static code.name.monkey.retromusic.Constants.RATE_ON_GOOGLE_PLAY; -import static code.name.monkey.retromusic.util.RetroUtil.openUrl; - import android.app.Activity; import android.app.ActivityOptions; import android.content.ActivityNotFoundException; @@ -24,8 +21,12 @@ import android.content.Context; import android.content.Intent; import android.media.audiofx.AudioEffect; import android.widget.Toast; + import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; + +import org.jetbrains.annotations.NotNull; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.activities.AboutActivity; import code.name.monkey.retromusic.activities.AlbumDetailsActivity; @@ -46,7 +47,9 @@ import code.name.monkey.retromusic.activities.bugreport.BugReportActivity; import code.name.monkey.retromusic.helper.MusicPlayerRemote; import code.name.monkey.retromusic.model.Genre; import code.name.monkey.retromusic.model.Playlist; -import org.jetbrains.annotations.NotNull; + +import static code.name.monkey.retromusic.Constants.RATE_ON_GOOGLE_PLAY; +import static code.name.monkey.retromusic.util.RetroUtil.openUrl; public class NavigationUtil { @@ -66,8 +69,8 @@ public class NavigationUtil { } public static void goToAlbumOptions(@NonNull Activity activity, - int albumId, - @NonNull ActivityOptions options) { + int albumId, + @NonNull ActivityOptions options) { Intent intent = new Intent(activity, AlbumDetailsActivity.class); intent.putExtra(AlbumDetailsActivity.EXTRA_ALBUM_ID, albumId); ActivityCompat.startActivity(activity, intent, options.toBundle()); @@ -80,8 +83,8 @@ public class NavigationUtil { } public static void goToArtistOptions(@NotNull Activity activity, - int artistId, - @NonNull ActivityOptions options) { + int artistId, + @NonNull ActivityOptions options) { Intent intent = new Intent(activity, ArtistDetailActivity.class); intent.putExtra(ArtistDetailActivity.EXTRA_ARTIST_ID, artistId); @@ -123,13 +126,13 @@ public class NavigationUtil { } public static void goToSearch(@NonNull Activity activity, - @NonNull ActivityOptions activityOptions) { + @NonNull ActivityOptions activityOptions) { ActivityCompat.startActivity(activity, new Intent(activity, SearchActivity.class), activityOptions.toBundle()); } public static void goToSearch(@NonNull Activity activity, boolean isMicOpen, - @NonNull ActivityOptions activityOptions) { + @NonNull ActivityOptions activityOptions) { ActivityCompat.startActivity(activity, new Intent(activity, SearchActivity.class) .putExtra(SearchActivity.EXTRA_SHOW_MIC, isMicOpen), activityOptions.toBundle()); @@ -144,7 +147,7 @@ public class NavigationUtil { } public static void goToUserInfo(@NonNull Activity activity, - @NonNull ActivityOptions activityOptions) { + @NonNull ActivityOptions activityOptions) { ActivityCompat.startActivity(activity, new Intent(activity, UserInfoActivity.class), activityOptions.toBundle()); } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java index 422f9a21..b6df807e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java @@ -14,8 +14,6 @@ package code.name.monkey.retromusic.util; -import static android.provider.MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI; - import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -25,24 +23,29 @@ import android.os.Environment; import android.provider.BaseColumns; import android.provider.MediaStore; import android.widget.Toast; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import code.name.monkey.retromusic.R; -import code.name.monkey.retromusic.helper.M3UWriter; -import code.name.monkey.retromusic.model.Playlist; -import code.name.monkey.retromusic.model.PlaylistSong; -import code.name.monkey.retromusic.model.Song; + import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import code.name.monkey.retromusic.R; +import code.name.monkey.retromusic.helper.M3UWriter; +import code.name.monkey.retromusic.model.Playlist; +import code.name.monkey.retromusic.model.PlaylistSong; +import code.name.monkey.retromusic.model.Song; + +import static android.provider.MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI; + public class PlaylistsUtil { public static void addToPlaylist(@NonNull Context context, - @NonNull List songs, - int playlistId, - boolean showToastOnFinish) { + @NonNull List songs, + int playlistId, + boolean showToastOnFinish) { ArrayList noSongs = new ArrayList(); for (Song song : songs) { @@ -130,7 +133,7 @@ public class PlaylistsUtil { } static boolean doPlaylistContains(@NonNull final Context context, final long playlistId, - final int songId) { + final int songId) { if (playlistId != -1) { try { Cursor c = context.getContentResolver().query( @@ -179,7 +182,7 @@ public class PlaylistsUtil { @NonNull public static ContentValues[] makeInsertItems(@NonNull final List songs, final int offset, int len, - final int base) { + final int base) { if (offset + len > songs.size()) { len = songs.size() - offset; } @@ -246,21 +249,21 @@ public class PlaylistsUtil { @Nullable public static File savePlaylist(@NonNull Context context, - @NonNull Playlist playlist) throws IOException { + @NonNull Playlist playlist) throws IOException { return M3UWriter.write(context, new File(Environment.getExternalStorageDirectory(), "Playlists"), playlist); } static void addToPlaylist(@NonNull Context context, - @NonNull Song song, - int playlistId, - boolean showToastOnFinish) { + @NonNull Song song, + int playlistId, + boolean showToastOnFinish) { List helperList = new ArrayList<>(); helperList.add(song); addToPlaylist(context, helperList, playlistId, showToastOnFinish); } private static boolean doesPlaylistExist(@NonNull Context context, @NonNull final String selection, - @NonNull final String[] values) { + @NonNull final String[] values) { Cursor cursor = context.getContentResolver().query(EXTERNAL_CONTENT_URI, new String[]{}, selection, values, null); diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java index 02cffb40..d54dfaeb 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java @@ -24,10 +24,24 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.preference.PreferenceManager; +import android.util.Log; + import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.StyleRes; import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.bottomnavigation.LabelVisibilityMode; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; + +import java.io.File; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.dialogs.OptionsSheetDialogFragment; import code.name.monkey.retromusic.fragments.AlbumCoverStyle; @@ -44,15 +58,6 @@ import code.name.monkey.retromusic.transform.HorizontalFlipTransformation; import code.name.monkey.retromusic.transform.NormalPageTransformer; import code.name.monkey.retromusic.transform.VerticalFlipTransformation; import code.name.monkey.retromusic.transform.VerticalStackTransformer; -import com.google.android.material.bottomnavigation.LabelVisibilityMode; -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; -import com.google.gson.reflect.TypeToken; -import java.io.File; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; public final class PreferenceUtil { @@ -133,37 +138,21 @@ public final class PreferenceUtil { public static final String TAB_TEXT_MODE = "tab_text_mode"; public static final String SAF_SDCARD_URI = "saf_sdcard_uri"; - - private static final String GENRE_SORT_ORDER = "genre_sort_order"; - - private static final String LAST_PAGE = "last_start_page"; - - private static final String BLUETOOTH_PLAYBACK = "bluetooth_playback"; - - private static final String LAST_MUSIC_CHOOSER = "last_music_chooser"; - - private static final String DEFAULT_START_PAGE = "default_start_page"; - - private static final String INITIALIZED_BLACKLIST = "initialized_blacklist"; - - private static final String ARTIST_SORT_ORDER = "artist_sort_order"; - - private static final String ARTIST_SONG_SORT_ORDER = "artist_song_sort_order"; - - private static final String ARTIST_ALBUM_SORT_ORDER = "artist_album_sort_order"; - - private static final String ALBUM_SORT_ORDER = "album_sort_order"; - - private static final String ALBUM_SONG_SORT_ORDER = "album_song_sort_order"; - public static final String SONG_SORT_ORDER = "song_sort_order"; - - private static final String ALBUM_GRID_SIZE = "album_grid_size"; - - private static final String ALBUM_GRID_SIZE_LAND = "album_grid_size_land"; - public static final String SONG_GRID_SIZE = "song_grid_size"; - + private static final String GENRE_SORT_ORDER = "genre_sort_order"; + private static final String LAST_PAGE = "last_start_page"; + private static final String BLUETOOTH_PLAYBACK = "bluetooth_playback"; + private static final String LAST_MUSIC_CHOOSER = "last_music_chooser"; + private static final String DEFAULT_START_PAGE = "default_start_page"; + private static final String INITIALIZED_BLACKLIST = "initialized_blacklist"; + private static final String ARTIST_SORT_ORDER = "artist_sort_order"; + private static final String ARTIST_SONG_SORT_ORDER = "artist_song_sort_order"; + private static final String ARTIST_ALBUM_SORT_ORDER = "artist_album_sort_order"; + private static final String ALBUM_SORT_ORDER = "album_sort_order"; + private static final String ALBUM_SONG_SORT_ORDER = "album_song_sort_order"; + private static final String ALBUM_GRID_SIZE = "album_grid_size"; + private static final String ALBUM_GRID_SIZE_LAND = "album_grid_size_land"; private static final String SONG_GRID_SIZE_LAND = "song_grid_size_land"; private static final String ARTIST_GRID_SIZE = "artist_grid_size"; @@ -227,11 +216,14 @@ public final class PreferenceUtil { private static final String SNOW_FALL_EFFECT = "snow_fall_effect"; private static final String FILTER_SONG = "filter_song"; - + private static final String TAG = "PreferenceUtil"; private static PreferenceUtil sInstance; - private final SharedPreferences mPreferences; + private PreferenceUtil(@NonNull final Context context) { + mPreferences = PreferenceManager.getDefaultSharedPreferences(context); + } + @NonNull public static PreferenceUtil getInstance(Context context) { if (sInstance == null) { @@ -267,10 +259,6 @@ public final class PreferenceUtil { } } - private PreferenceUtil(@NonNull final Context context) { - mPreferences = PreferenceManager.getDefaultSharedPreferences(context); - } - public final boolean albumArtOnLockscreen() { return mPreferences.getBoolean(ALBUM_ART_ON_LOCKSCREEN, true); } @@ -410,6 +398,9 @@ public final class PreferenceUtil { @LayoutRes public int getAlbumGridStyle() { + if (mPreferences.contains(ALBUM_GRID_STYLE)) { + Log.i(TAG, "getAlbumGridStyle: " + mPreferences.getInt(ALBUM_GRID_STYLE, -10)); + } return mPreferences.getInt(ALBUM_GRID_STYLE, R.layout.item_grid); } @@ -461,6 +452,9 @@ public final class PreferenceUtil { @LayoutRes public int getArtistGridStyle() { + if (mPreferences.contains(ARTIST_GRID_STYLE)) { + Log.i(TAG, "getArtistGridStyle: " + mPreferences.getInt(ARTIST_GRID_STYLE, -10)); + } return mPreferences.getInt(ARTIST_GRID_STYLE, R.layout.item_grid); } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/RetroColorUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/RetroColorUtil.java index 7e93bff2..d41c69c6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/RetroColorUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/RetroColorUtil.java @@ -29,9 +29,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import code.name.monkey.appthemehelper.util.ATHUtil; import code.name.monkey.appthemehelper.util.ColorUtil; -import code.name.monkey.retromusic.R; public class RetroColorUtil { public static int desaturateColor(int color, float ratio) { diff --git a/app/src/main/java/code/name/monkey/retromusic/util/RetroUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/RetroUtil.java index 80a0bc49..d4f5d368 100755 --- a/app/src/main/java/code/name/monkey/retromusic/util/RetroUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/RetroUtil.java @@ -35,14 +35,17 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; + import androidx.annotation.ColorInt; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; + +import java.text.DecimalFormat; + import code.name.monkey.appthemehelper.util.TintHelper; import code.name.monkey.retromusic.App; -import java.text.DecimalFormat; public class RetroUtil { @@ -105,20 +108,20 @@ public class RetroUtil { @Nullable public static Drawable getTintedVectorDrawable(@NonNull Context context, @DrawableRes int id, - @ColorInt int color) { + @ColorInt int color) { return TintHelper.createTintedDrawable( getVectorDrawable(context.getResources(), id, context.getTheme()), color); } @Nullable public static Drawable getTintedVectorDrawable(@NonNull Resources res, @DrawableRes int resId, - @Nullable Resources.Theme theme, @ColorInt int color) { + @Nullable Resources.Theme theme, @ColorInt int color) { return TintHelper.createTintedDrawable(getVectorDrawable(res, resId, theme), color); } @Nullable public static Drawable getVectorDrawable(@NonNull Resources res, @DrawableRes int resId, - @Nullable Resources.Theme theme) { + @Nullable Resources.Theme theme) { if (Build.VERSION.SDK_INT >= 21) { return res.getDrawable(resId, theme); } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/RingtoneManager.kt b/app/src/main/java/code/name/monkey/retromusic/util/RingtoneManager.kt index 013587f3..dfe7e725 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/RingtoneManager.kt +++ b/app/src/main/java/code/name/monkey/retromusic/util/RingtoneManager.kt @@ -45,16 +45,18 @@ class RingtoneManager(val context: Context) { try { - val cursor = resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - arrayOf(MediaStore.MediaColumns.TITLE), - BaseColumns._ID + "=?", - arrayOf(song.id.toString()), null) + val cursor = resolver.query( + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + arrayOf(MediaStore.MediaColumns.TITLE), + BaseColumns._ID + "=?", + arrayOf(song.id.toString()), null + ) cursor.use { cursorSong -> if (cursorSong != null && cursorSong.count == 1) { cursorSong.moveToFirst() Settings.System.putString(resolver, Settings.System.RINGTONE, uri.toString()) val message = context - .getString(R.string.x_has_been_set_as_ringtone, cursorSong.getString(0)) + .getString(R.string.x_has_been_set_as_ringtone, cursorSong.getString(0)) Toast.makeText(context, message, Toast.LENGTH_SHORT).show() } } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/SwipeAndDragHelper.java b/app/src/main/java/code/name/monkey/retromusic/util/SwipeAndDragHelper.java index f8fa85da..a5f740db 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/SwipeAndDragHelper.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/SwipeAndDragHelper.java @@ -17,8 +17,8 @@ package code.name.monkey.retromusic.util; import android.graphics.Canvas; import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; public class SwipeAndDragHelper extends ItemTouchHelper.Callback { diff --git a/app/src/main/java/code/name/monkey/retromusic/util/ThemeManager.kt b/app/src/main/java/code/name/monkey/retromusic/util/ThemeManager.kt index 30eb755c..4eaa224b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/ThemeManager.kt +++ b/app/src/main/java/code/name/monkey/retromusic/util/ThemeManager.kt @@ -13,18 +13,21 @@ import code.name.monkey.retromusic.R object ThemeManager { @StyleRes - fun getThemeResValue(context: Context): Int = when (PreferenceUtil.getInstance(context).generalThemeValue) { - "light" -> R.style.Theme_RetroMusic_Light - "dark" -> R.style.Theme_RetroMusic_Base - "auto" -> R.style.Theme_RetroMusic_FollowSystem - "black" -> R.style.Theme_RetroMusic_Black - else -> R.style.Theme_RetroMusic_FollowSystem - } + fun getThemeResValue(context: Context): Int = + when (PreferenceUtil.getInstance(context).generalThemeValue) { + "light" -> R.style.Theme_RetroMusic_Light + "dark" -> R.style.Theme_RetroMusic_Base + "auto" -> R.style.Theme_RetroMusic_FollowSystem + "black" -> R.style.Theme_RetroMusic_Black + else -> R.style.Theme_RetroMusic_FollowSystem + } private fun isSystemDarkModeEnabled(context: Context): Boolean { - val isBatterySaverEnabled = (context.getSystemService(Context.POWER_SERVICE) as PowerManager?)?.isPowerSaveMode + val isBatterySaverEnabled = + (context.getSystemService(Context.POWER_SERVICE) as PowerManager?)?.isPowerSaveMode ?: false - val isDarkModeEnabled = (context.resources.configuration.uiMode and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES + val isDarkModeEnabled = + (context.resources.configuration.uiMode and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES return isBatterySaverEnabled or isDarkModeEnabled } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt b/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt index 15438f9a..dcc75ba7 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt +++ b/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt @@ -67,7 +67,8 @@ object ViewUtil { BlendModeColorFilterCompat.createBlendModeColorFilterCompat(newColor, SRC_IN) val background = layerDrawable.findDrawableByLayerId(android.R.id.background) - val primaryColor = ATHUtil.resolveColor(progressSlider.context, android.R.attr.windowBackground) + val primaryColor = + ATHUtil.resolveColor(progressSlider.context, android.R.attr.windowBackground) background.colorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat( MaterialValueHelper.getPrimaryDisabledTextColor( progressSlider.context, @@ -77,7 +78,12 @@ object ViewUtil { val secondaryProgress = layerDrawable.findDrawableByLayerId(android.R.id.secondaryProgress) secondaryProgress?.colorFilter = - BlendModeColorFilterCompat.createBlendModeColorFilterCompat(ColorUtil.withAlpha(newColor, 0.65f), SRC_IN) + BlendModeColorFilterCompat.createBlendModeColorFilterCompat( + ColorUtil.withAlpha( + newColor, + 0.65f + ), SRC_IN + ) } fun hitTest(v: View, x: Int, y: Int): Boolean { diff --git a/app/src/main/java/code/name/monkey/retromusic/views/BaselineGridTextView.java b/app/src/main/java/code/name/monkey/retromusic/views/BaselineGridTextView.java index 7d82b758..8cce44b1 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/BaselineGridTextView.java +++ b/app/src/main/java/code/name/monkey/retromusic/views/BaselineGridTextView.java @@ -19,10 +19,13 @@ import android.content.res.TypedArray; import android.graphics.Paint; import android.util.AttributeSet; import android.util.TypedValue; + import androidx.annotation.FontRes; -import code.name.monkey.retromusic.R; + import com.google.android.material.textview.MaterialTextView; +import code.name.monkey.retromusic.R; + public class BaselineGridTextView extends MaterialTextView { private final float FOUR_DIP; diff --git a/app/src/main/java/code/name/monkey/retromusic/views/BottomNavigationBarTinted.kt b/app/src/main/java/code/name/monkey/retromusic/views/BottomNavigationBarTinted.kt index 71d4ad81..c7e6f155 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/BottomNavigationBarTinted.kt +++ b/app/src/main/java/code/name/monkey/retromusic/views/BottomNavigationBarTinted.kt @@ -41,8 +41,16 @@ class BottomNavigationBarTinted @JvmOverloads constructor( val iconColor = ATHUtil.resolveColor(context, android.R.attr.colorControlNormal) val accentColor = ThemeStore.accentColor(context) - NavigationViewUtil.setItemIconColors(this, ColorUtil.withAlpha(iconColor, 0.5f), accentColor) - NavigationViewUtil.setItemTextColors(this, ColorUtil.withAlpha(iconColor, 0.5f), accentColor) + NavigationViewUtil.setItemIconColors( + this, + ColorUtil.withAlpha(iconColor, 0.5f), + accentColor + ) + NavigationViewUtil.setItemTextColors( + this, + ColorUtil.withAlpha(iconColor, 0.5f), + accentColor + ) itemBackground = RippleDrawable( RippleUtils.convertToRippleDrawableColor( ColorStateList.valueOf( diff --git a/app/src/main/java/code/name/monkey/retromusic/views/BreadCrumbLayout.java b/app/src/main/java/code/name/monkey/retromusic/views/BreadCrumbLayout.java index d8c3d131..944ca9c1 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/BreadCrumbLayout.java +++ b/app/src/main/java/code/name/monkey/retromusic/views/BreadCrumbLayout.java @@ -26,156 +26,35 @@ import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; + import androidx.annotation.ColorInt; import androidx.annotation.NonNull; -import code.name.monkey.appthemehelper.util.ATHUtil; -import code.name.monkey.retromusic.R; + import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import code.name.monkey.appthemehelper.util.ATHUtil; +import code.name.monkey.retromusic.R; + /** * @author Aidan Follestad (afollestad), modified for Phonograph by Karim Abou Zeid (kabouzeid) */ public class BreadCrumbLayout extends HorizontalScrollView implements View.OnClickListener { - public static class Crumb implements Parcelable { - - public static final Creator CREATOR = new Creator() { - @Override - public Crumb createFromParcel(Parcel source) { - return new Crumb(source); - } - - @Override - public Crumb[] newArray(int size) { - return new Crumb[size]; - } - }; - - private final File file; - - private int scrollPos; - - public Crumb(File file) { - this.file = file; - } - - protected Crumb(Parcel in) { - this.file = (File) in.readSerializable(); - this.scrollPos = in.readInt(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public boolean equals(Object o) { - return (o instanceof Crumb) && ((Crumb) o).getFile() != null && - ((Crumb) o).getFile().equals(getFile()); - } - - public File getFile() { - return file; - } - - public int getScrollPosition() { - return scrollPos; - } - - public void setScrollPosition(int scrollY) { - this.scrollPos = scrollY; - } - - public String getTitle() { - return file.getPath().equals("/") ? "root" : file.getName(); - } - - @Override - public String toString() { - return "Crumb{" + - "file=" + file + - ", scrollPos=" + scrollPos + - '}'; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeSerializable(this.file); - dest.writeInt(this.scrollPos); - } - } - - public static class SavedStateWrapper implements Parcelable { - - public static final Creator CREATOR = new Creator() { - public SavedStateWrapper createFromParcel(Parcel source) { - return new SavedStateWrapper(source); - } - - public SavedStateWrapper[] newArray(int size) { - return new SavedStateWrapper[size]; - } - }; - - public final int mActive; - - public final List mCrumbs; - - public final int mVisibility; - - public SavedStateWrapper(BreadCrumbLayout view) { - mActive = view.mActive; - mCrumbs = view.mCrumbs; - mVisibility = view.getVisibility(); - } - - protected SavedStateWrapper(Parcel in) { - this.mActive = in.readInt(); - this.mCrumbs = in.createTypedArrayList(Crumb.CREATOR); - this.mVisibility = in.readInt(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.mActive); - dest.writeTypedList(mCrumbs); - dest.writeInt(this.mVisibility); - } - } - - public interface SelectionCallback { - - void onCrumbSelection(Crumb crumb, int index); - } - @ColorInt private int contentColorActivated; - @ColorInt private int contentColorDeactivated; - private int mActive; - private SelectionCallback mCallback; - private LinearLayout mChildFrame; - // Stores currently visible crumbs private List mCrumbs; - // Stores user's navigation history, like a fragment back stack private List mHistory; - // Used in setActiveOrAdd() between clearing crumbs and adding the new set, nullified afterwards private List mOldCrumbs; @@ -422,7 +301,7 @@ public class BreadCrumbLayout extends HorizontalScrollView implements View.OnCli } private TextView invalidateActivated(View view, final boolean isActive, final boolean noArrowIfAlone, - final boolean allowArrowVisible) { + final boolean allowArrowVisible) { int contentColor = isActive ? contentColorActivated : contentColorDeactivated; LinearLayout child = (LinearLayout) view; TextView tv = (TextView) child.getChildAt(0); @@ -448,4 +327,121 @@ public class BreadCrumbLayout extends HorizontalScrollView implements View.OnCli } return success; } + + public interface SelectionCallback { + + void onCrumbSelection(Crumb crumb, int index); + } + + public static class Crumb implements Parcelable { + + public static final Creator CREATOR = new Creator() { + @Override + public Crumb createFromParcel(Parcel source) { + return new Crumb(source); + } + + @Override + public Crumb[] newArray(int size) { + return new Crumb[size]; + } + }; + + private final File file; + + private int scrollPos; + + public Crumb(File file) { + this.file = file; + } + + protected Crumb(Parcel in) { + this.file = (File) in.readSerializable(); + this.scrollPos = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public boolean equals(Object o) { + return (o instanceof Crumb) && ((Crumb) o).getFile() != null && + ((Crumb) o).getFile().equals(getFile()); + } + + public File getFile() { + return file; + } + + public int getScrollPosition() { + return scrollPos; + } + + public void setScrollPosition(int scrollY) { + this.scrollPos = scrollY; + } + + public String getTitle() { + return file.getPath().equals("/") ? "root" : file.getName(); + } + + @Override + public String toString() { + return "Crumb{" + + "file=" + file + + ", scrollPos=" + scrollPos + + '}'; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeSerializable(this.file); + dest.writeInt(this.scrollPos); + } + } + + public static class SavedStateWrapper implements Parcelable { + + public static final Creator CREATOR = new Creator() { + public SavedStateWrapper createFromParcel(Parcel source) { + return new SavedStateWrapper(source); + } + + public SavedStateWrapper[] newArray(int size) { + return new SavedStateWrapper[size]; + } + }; + + public final int mActive; + + public final List mCrumbs; + + public final int mVisibility; + + public SavedStateWrapper(BreadCrumbLayout view) { + mActive = view.mActive; + mCrumbs = view.mCrumbs; + mVisibility = view.getVisibility(); + } + + protected SavedStateWrapper(Parcel in) { + this.mActive = in.readInt(); + this.mCrumbs = in.createTypedArrayList(Crumb.CREATOR); + this.mVisibility = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(this.mActive); + dest.writeTypedList(mCrumbs); + dest.writeInt(this.mVisibility); + } + } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/views/CircularImageView.java b/app/src/main/java/code/name/monkey/retromusic/views/CircularImageView.java index d99f77bd..3b555cf2 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/CircularImageView.java +++ b/app/src/main/java/code/name/monkey/retromusic/views/CircularImageView.java @@ -25,10 +25,11 @@ import android.graphics.Paint; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import androidx.appcompat.widget.AppCompatImageView; import android.util.AttributeSet; import android.util.Log; +import androidx.appcompat.widget.AppCompatImageView; + import code.name.monkey.retromusic.R; public class CircularImageView extends AppCompatImageView { diff --git a/app/src/main/java/code/name/monkey/retromusic/views/ContributorsView.java b/app/src/main/java/code/name/monkey/retromusic/views/ContributorsView.java index cd72ea55..f5e25904 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/ContributorsView.java +++ b/app/src/main/java/code/name/monkey/retromusic/views/ContributorsView.java @@ -25,6 +25,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import code.name.monkey.retromusic.R; import static code.name.monkey.retromusic.util.RetroUtil.openUrl; diff --git a/app/src/main/java/code/name/monkey/retromusic/views/ListItemView.kt b/app/src/main/java/code/name/monkey/retromusic/views/ListItemView.kt index aea3312c..0a0ca03a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/ListItemView.kt +++ b/app/src/main/java/code/name/monkey/retromusic/views/ListItemView.kt @@ -37,7 +37,11 @@ class ListItemView : FrameLayout { init(context, attrs) } - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { init(context, attrs) } diff --git a/app/src/main/java/code/name/monkey/retromusic/views/MetalRecyclerViewPager.kt b/app/src/main/java/code/name/monkey/retromusic/views/MetalRecyclerViewPager.kt index c044bd26..29bab7ba 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/MetalRecyclerViewPager.kt +++ b/app/src/main/java/code/name/monkey/retromusic/views/MetalRecyclerViewPager.kt @@ -36,15 +36,21 @@ class MetalRecyclerViewPager : RecyclerView { init(context, attrs) } - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { init(context, attrs) } private var itemMargin: Int = 0 fun init(context: Context, attrs: AttributeSet?) { - val typedArray = context.obtainStyledAttributes(attrs, R.styleable.MetalRecyclerViewPager, 0, 0) - itemMargin = typedArray.getDimension(R.styleable.MetalRecyclerViewPager_itemMargin, 0f).toInt() + val typedArray = + context.obtainStyledAttributes(attrs, R.styleable.MetalRecyclerViewPager, 0, 0) + itemMargin = + typedArray.getDimension(R.styleable.MetalRecyclerViewPager_itemMargin, 0f).toInt() typedArray.recycle() layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) @@ -62,7 +68,8 @@ class MetalRecyclerViewPager : RecyclerView { super.setAdapter(adapter) } - abstract class MetalAdapter(@NonNull val displayMetrics: DisplayMetrics) : RecyclerView.Adapter() { + abstract class MetalAdapter(@NonNull val displayMetrics: DisplayMetrics) : + RecyclerView.Adapter() { private var itemMargin: Int = 0 private var itemWidth: Int = 0 diff --git a/app/src/main/java/code/name/monkey/retromusic/views/PopupBackground.java b/app/src/main/java/code/name/monkey/retromusic/views/PopupBackground.java index 4bdac34a..0d6c6737 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/PopupBackground.java +++ b/app/src/main/java/code/name/monkey/retromusic/views/PopupBackground.java @@ -27,9 +27,11 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.view.View; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.graphics.drawable.DrawableCompat; + import code.name.monkey.appthemehelper.ThemeStore; import code.name.monkey.retromusic.R; @@ -58,6 +60,12 @@ public class PopupBackground extends Drawable { mPaddingEnd = resources.getDimensionPixelOffset(R.dimen.afs_md2_popup_padding_end); } + private static void pathArcTo(@NonNull Path path, float centerX, float centerY, float radius, + float startAngle, float sweepAngle) { + path.arcTo(centerX - radius, centerY - radius, centerX + radius, centerY + radius, + startAngle, sweepAngle, false); + } + @Override public void draw(@NonNull Canvas canvas) { canvas.drawPath(mPath, mPaint); @@ -146,10 +154,4 @@ public class PopupBackground extends Drawable { mTempMatrix.postTranslate(bounds.left, bounds.top); mPath.transform(mTempMatrix); } - - private static void pathArcTo(@NonNull Path path, float centerX, float centerY, float radius, - float startAngle, float sweepAngle) { - path.arcTo(centerX - radius, centerY - radius, centerX + radius, centerY + radius, - startAngle, sweepAngle, false); - } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/views/ScrollingViewOnApplyWindowInsetsListener.java b/app/src/main/java/code/name/monkey/retromusic/views/ScrollingViewOnApplyWindowInsetsListener.java index d8f49015..1abe0bac 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/ScrollingViewOnApplyWindowInsetsListener.java +++ b/app/src/main/java/code/name/monkey/retromusic/views/ScrollingViewOnApplyWindowInsetsListener.java @@ -20,6 +20,7 @@ import android.view.WindowInsets; import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import me.zhanghai.android.fastscroll.FastScroller; public class ScrollingViewOnApplyWindowInsetsListener implements View.OnApplyWindowInsetsListener { diff --git a/app/src/main/java/code/name/monkey/retromusic/views/SeekArc.java b/app/src/main/java/code/name/monkey/retromusic/views/SeekArc.java index 38128504..726a5f73 100644 --- a/app/src/main/java/code/name/monkey/retromusic/views/SeekArc.java +++ b/app/src/main/java/code/name/monkey/retromusic/views/SeekArc.java @@ -24,11 +24,12 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; + import code.name.monkey.retromusic.R; /** * SeekArc.java - * + *

* This is a class that functions much like a SeekBar but * follows a circle path instead of a straight line. * @@ -36,129 +37,70 @@ import code.name.monkey.retromusic.R; */ public class SeekArc extends View { - public interface OnSeekArcChangeListener { - - /** - * Notification that the progress level has changed. Clients can use the - * fromUser parameter to distinguish user-initiated changes from those - * that occurred programmatically. - * - * @param seekArc The SeekArc whose progress has changed - * @param progress The current progress level. This will be in the range - * 0..max where max was set by - * {@link ProgressArc#setMax(int)}. (The default value for - * max is 100.) - * @param fromUser True if the progress change was initiated by the user. - */ - void onProgressChanged(SeekArc seekArc, int progress, boolean fromUser); - - /** - * Notification that the user has started a touch gesture. Clients may - * want to use this to disable advancing the seekbar. - * - * @param seekArc The SeekArc in which the touch gesture began - */ - void onStartTrackingTouch(SeekArc seekArc); - - /** - * Notification that the user has finished a touch gesture. Clients may - * want to use this to re-enable advancing the seekarc. - * - * @param seekArc The SeekArc in which the touch gesture began - */ - void onStopTrackingTouch(SeekArc seekArc); - } - private static final String TAG = SeekArc.class.getSimpleName(); - private static int INVALID_PROGRESS_VALUE = -1; - // The initial rotational offset -90 means we start at 12 o'clock private final int mAngleOffset = -90; - private Paint mArcPaint; - // Internal variables private int mArcRadius = 0; - private RectF mArcRect = new RectF(); - /** * The Width of the background arc for the SeekArc */ private int mArcWidth = 2; - /** * Will the progress increase clockwise or anti-clockwise */ private boolean mClockwise = true; - /** * is the control enabled/touchable */ private boolean mEnabled = true; - /** * The Maximum value that this SeekArc can be set to */ private int mMax = 100; - private OnSeekArcChangeListener mOnSeekArcChangeListener; - /** * The Current value that the SeekArc is set to */ private int mProgress = 0; - private Paint mProgressPaint; - private float mProgressSweep = 0; - /** * The width of the progress line for this SeekArc */ private int mProgressWidth = 4; - /** * The rotation of the SeekArc- 0 is twelve o'clock */ private int mRotation = 0; - /** * Give the SeekArc rounded edges */ private boolean mRoundedEdges = false; - /** * The Angle to start drawing this Arc from */ private int mStartAngle = 0; - /** * The Angle through which to draw the arc (Max is 360) */ private int mSweepAngle = 360; - /** * The Drawable for the seek arc thumbnail */ private Drawable mThumb; - private int mThumbXPos; - private int mThumbYPos; - private double mTouchAngle; - private float mTouchIgnoreRadius; - /** * Enable touch inside the SeekArc */ private boolean mTouchInside = true; - private int mTranslateX; - private int mTranslateY; public SeekArc(Context context) { @@ -574,4 +516,37 @@ public class SeekArc extends View { private float valuePerDegree() { return (float) mMax / mSweepAngle; } + + public interface OnSeekArcChangeListener { + + /** + * Notification that the progress level has changed. Clients can use the + * fromUser parameter to distinguish user-initiated changes from those + * that occurred programmatically. + * + * @param seekArc The SeekArc whose progress has changed + * @param progress The current progress level. This will be in the range + * 0..max where max was set by + * {@link ProgressArc#setMax(int)}. (The default value for + * max is 100.) + * @param fromUser True if the progress change was initiated by the user. + */ + void onProgressChanged(SeekArc seekArc, int progress, boolean fromUser); + + /** + * Notification that the user has started a touch gesture. Clients may + * want to use this to disable advancing the seekbar. + * + * @param seekArc The SeekArc in which the touch gesture began + */ + void onStartTrackingTouch(SeekArc seekArc); + + /** + * Notification that the user has finished a touch gesture. Clients may + * want to use this to re-enable advancing the seekarc. + * + * @param seekArc The SeekArc in which the touch gesture began + */ + void onStopTrackingTouch(SeekArc seekArc); + } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java b/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java index f11c4bd3..2378cc36 100644 --- a/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java +++ b/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java @@ -18,6 +18,7 @@ import android.database.ContentObserver; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; + import androidx.annotation.NonNull; public class AudioVolumeContentObserver extends ContentObserver { @@ -31,8 +32,8 @@ public class AudioVolumeContentObserver extends ContentObserver { private float mLastVolume; AudioVolumeContentObserver(@NonNull Handler handler, @NonNull AudioManager audioManager, - int audioStreamType, - @NonNull OnAudioVolumeChangedListener listener) { + int audioStreamType, + @NonNull OnAudioVolumeChangedListener listener) { super(handler); mAudioManager = audioManager; diff --git a/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeObserver.java b/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeObserver.java index 7e97571c..e5b002a5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeObserver.java +++ b/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeObserver.java @@ -17,6 +17,7 @@ package code.name.monkey.retromusic.volume; import android.content.Context; import android.media.AudioManager; import android.os.Handler; + import androidx.annotation.NonNull; public class AudioVolumeObserver { diff --git a/app/src/main/res/drawable-hdpi/default_album_art.webp b/app/src/main/res/drawable-hdpi/default_album_art.webp index 11a82d86d6dc3017f9870d9fa389ebdbb803f575..7444895683a8e692ce792b865bbf0ad7781198af 100644 GIT binary patch literal 4522 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 Dz$}HU diff --git a/app/src/main/res/drawable-hdpi/default_artist_art.webp b/app/src/main/res/drawable-hdpi/default_artist_art.webp index 1576defdc7a60746605c3c77518ace28c59df639..bb551b29ec1b0c351b391b5ec281a4c9e0213418 100644 GIT binary patch literal 2692 zcmb`?_dgVj0|#*FGM?z1y`LLqcDR%x<46ieID2F}dyfd`I{P?;?E6M$<`J?BXOGHu zF7=R+$PD-N`u+{i>-GNO^V8?``55cz=tTZSM`w=EG%_<%dFcBm%SmdH>Fi))k5GW$ zu7@kQlpNZYFIC=c;lA<6-yuh~bRdOGxOENCwQ4O*1SUud5*H`)I05fh#TFvyzY^_l z2VLB+!byNOjRewz#6j%oeo`RDPuwL?$HnVBXs?Cs>oxFo6b?Eoih{!L#c{FraHDy% zv>mU+OV1zEy6mGx`8-F$c6SK43q!hCl9%GeZsU3CIt{==+gJbZbSXs;12z_ISC6aD z&Z)mVqZHeDfoE4Cq;R9Cjh{u;E1Zoc%h9YXHCg;;FBU$(RRCU$3VybD9gw>RTe;sk zR$4%CpSbE$wbg5>78|l^^W0`$HO0|}7L~LV$vyD4)A9L|ZEBqLyu+1@f`wLZH zSfLVU&IKoN=v48+k7X^Faz>aPKLP}va#WFBJde|_k7385rbB^2K!Yo)WnV-LUdzYkzL^3ws#ohBkMlnNIRDAdDJ zo29UgTOr24mNb~Q&PhtR63E|_kg0Ytd*&Y;pi40e50<85gS^c7>?{(1be$~Nv*Z=( zfTtUYv1N$#F`;;Ur=>CWB4`h6mzU5ie8Ho*?FP&5Q zV5gIlqAhaDBpv62<^P<%7iz`I+*TTm1GYv2UEEnY zd?$T}B_v~IEtT}ryOY#jej#7B3$#y6EZR*n7~N$P0qkc!G7zxW0_`fF3Uk1 zwS-PcsS%Q}AfX{J8ETqz#96TjEo~xdykQf;5IY?Qg1)M_7r;s{&aVd(aahIe^d56=O=DDs!bojLOtYY8xt5ElOX>C(#5;(a;s0ccb~Wc^8V%642|pIrOfK>t}rWE`QQhB~+X zgg6l0d2qU4SywOrsT|>USbRpNg}m#?WhyoHg=VRqT}(MoZkPK*2)I^HvFMdA>d{?% zmx+{P@{7%z!2!R2M*0j2!A@?|4nE&x+w0HX`^sN+Obv;VJ5S2m8m4Go)V>cFyWbIg zp7QabzOPuw$%nQm*v5r5fot@ETkY=P>BSBqJJQ*dz<%6n=UiZ}7rd5{HJT9OQ9k8d z^FuGVZFF#^%hJ2?8#A&;@zYI_$wi>qMYhO*9dEYSQIQ3WS+C;SlML~&8G8=f42tyT zV%qTw27w!565}|f-IJJ7wi^Tw$VfM2?PgV8Bp{vs4^i9Xe3zctfWG^7iU*7yJ- z8t&q~ra&-jp;J$4e~`k`Q4FSm#VTHL7K?GK&e}eDZ=`#^!Wg* z4Rhv}P>!e;!c*p>(15|RaJURv#3JFqO& z4Dd=>pTmI5dE%Yz5#X^hgczOzP1@(h~6X3cRo+#1S}J{fh1=J6A* zDQX;+=Xg!$r(}S+U>1ASX0w(5C^_ zC}`_Hto|fv;Z@~+m&(VfL&s$Nw4yxRtC8q^I=*Zq0#^VfVLJL~XXF1J+7{!##q?TN literal 4062 zcmeH~`8yN}7stm^#&$8;w=fg3M@H$6vhPBek)4S!vdb8ZEykL$UfWsZ=ZUO}({008b^ zd6DTKX`5LZefm{mXoN_cBjkUwe9yqWJ!hy*gIf2N?mJPqZs^tc(Gp{;ufPr&$9zM7 zc&b&{dWN(%8dV87tv5{q%9oz75rgo)Pj|Q&ttbhP;Al_D^S6L9Q-dH*W8rKCDtWVz z@Z@%Zt~Iz{sYde_to!nWSDvSD>l&Sw33a9iq8b(nm;g^{`TvJ zCU&G`Z^qOs5-W077%}}x`NdOcP!BtnFj+6ge|zxYEWYthM3O$-zm%n8r;3phfRW3% zKc37+c@j+$+HfzBqfFbIExwPP5vD|4O%5b9O&w*Hah>T9-iD<6j3^_~=`?tCW0cy~YJVNF~FXM`RzA%&kOiPWMG z`S{3_hcq@gz<;QysqaS=DG~M~!b@+ov?{|irFZ_0%~+C*!AUzXdOi68F&a#5fX))mQ+1I=RXxHx_kGHam5qZd+QRa?^ECpPr>N)HLSK z60dY5BOiH=e=VJ_Z*ED^=W-gm2ee6h%g-adD6o9+tWx_L!JrW+c)no!)-xyJwp5L}#Fku!F_UZQx9#1m>GpDmx({|g}p6mECPG?@8<9@F3`Y0MD8Q=(|C6%RS z9bMT>$dDO^>L_hlc{LX81kNFIn~EClww6F*%nDF(?<39gk5D-hU-8f7tl)E#mEIs14uQip zp>WcP+dFj~UfNhqc$P%^i=_(XAAj3Zc*Wi_n=O;0S;ya^EEPF0);nY37m$-&j! zi7>R=+ece>n(F-nkBhmH{+S$zYOMb+tejY5e8Dm=ko}q`7~=KT<951z7&TbeD-t=P zb7JTcJn-=~a-aHcefwbBu~gjrK$IQtt#;=DeHHs(b-LkK)Jmd0yY#Eg%sh9{X!Me9 zu*H7b$O*l@pLpQh;5ktr2uE8_jIJNglz72GuDqJ)-Pu`8*f)}Z z=`HguBgeS~W%@o0i0(YxT{pqoMxG0Z#kywaelhhpm`a!1m@!$5zuxJkJ^`{wUooxQ zaLN)FRBR>MCx;-PirO7CGQE3=8K{-MFqwDpN?p+P!HiY=nc^QK>DOny>e(R}*N6Cv z)Xw8%b$>oSXJnM_yFb4seZfRO#L-1MWkK6;Pq^7hYcbDDDX!)95i zo%>SWiS@|e<+5l>|5<`mc{6A!ljIRU{2tQRI-;_?i5*H*${ceMN^Ey&ZcchoTvK65 zlP;op=Pb-1IW$jLiX!8Y)k1MuL#TZQp=LHl^?8qp^ErVtnZe&M5H`4-NtBt4`MhEWZb^w7w?CIyxZMnonZn%ye4y6+c_Cm+!DixO<9>Y!gcPDWtBzos)SH)yNLYGizpM?B#D& zSg5_&5Z47xMMD;d7mrjVRuFH=2@};<(iyI|yrOn66033UU1`HRZVWb1-2#<>UY`-u zaMwf@3Crd}EmmDm!JZfc^6Vv6!{Gp4ri|I)7tC@+WoClm)O+(d#N}=&V8}G5hS3^S zTLbw0wuMPtC(-2<7h_bOnq2J4_aZQ^U3oDr+Dpa9khz1prS8UyRV2DlqH|1AclZD_GGb#=U& zj_;~M{u*nVNZfy!rDG^xXp;dFB|MQNfONflBPK^c;^Hkt69h+9?QNS|%(!`&$Rf|x zkmLA2&S#v1%s(a0#fbVukh&?-J$+j8i;~*Bm@h8}E-}8kJDfsKVUzOj_Y+d?UhJ&H z1!v)AhwjNeJ*Q$IXJ>P2z^mTy%&Q7t7Wg{lN4WwqgLo}PEFmM+uFt7Q_DYAcKUULd zM^F}FbqSItOL#n3`)M&DvzY|#yBet1Y-Vereh!@Z{X?7Ny?jI74x3D?XS^56jvpbl zt7_PP0k8c>Rmy}Sb6$CK%HB@aHCzok;L-8(H>UB!34gsLJB~Mt(7P2+32QnVE!BP@HKof}7``*HRH<25xUzk3iij!W>T;+;t2@?N_T!!rrzQ$~3XCBaG kB)7>Hy1(1M$MSm}exJerMh64{KtG)a)~NmZ!~ehd4_j6~*#H0l diff --git a/app/src/main/res/drawable-hdpi/default_audio_art.webp b/app/src/main/res/drawable-hdpi/default_audio_art.webp index 10cb9228cbe2a59e46ea886eff4e32bea211bded..b5dc131ab65fa36fda9870c429a299fe3f6415b0 100644 GIT binary patch literal 1444 zcmb`>{XY{30LSrRt32FvO}B~8IJQ-Eoaar%JVct&nL0vqjV6!fAyZm}@w$@^^LU=q ztX)d;kcX{#$O$#ZEO}_x)jUidnlfzHUvNM5)BE#!eSi7-dAhrog8+a4Hy1nsZ|8mc zOaFKXI|%T>!Y}qrgzo4mLBL0cW-L#@%f!dh-=!UthYrOLsl0573iJ;%E8pXG-)i|U zTbI{`u((!;>Y_5OMq|TK`||Vz$yJFwE=iMDDjJmYUlpa2npbycKg@$O#N{c5r|1Nd zeKPv&L8UIW^LN>9R{vatDJW6Y2W8ESIwN0NFBh-}W8}w=b}^22Zl=f98Y~P*4_rC< ze!SvA)a1t2*$Q;-rE4Y$OVK(L{o`FoPkb333KieBsfr%)0I*nZQPaK6Pizx5_LRDf zj8FHG%*%Y~v#!;qr>~UaoJILhb}ZF?Wi80f;FyG9d$ll*U?^vp{f>c zQ{!lQW0C=V{5_8tavgTFi6HyOCS#Z)*5!d6sy%@nvOaA>>B}|3e zO$h^WuT#R*xW9BgB%|UpiLdZldO5S1Mp4M%KHQRSjs-TK4Y4I65mMLo3EWanMMMiE zi-_<#m1u+{iS5rL2Ge@Ihq6lsa!cC0i)mYr&(NmO5BJ@wJ40g?!)W5$RqY)kdVME4 z!5UQ^^9g7}8!_4RXz_CSRL~#XC)h#l&3eTF=Z&1=C-)1rM_r<6F!^AxrJ zL%O6iB>ggTDyxB>^x}h$Fgz>pNVA%m#bvyZj=3u21a?nVN*Qcb#tfUX^FBb6^TSF2 zCM9T8wb0Q<-GsUlPg2oDog^oQoj)+pl z=E3q^mk2mL`l@mNHxRS){K{?7Yvk0kVEp5-#oB|$?1^5_sX7czw zc9Z!{{I&Dd>eZu$hI_NS!MiaqwhmZs(P*hta0gb1xLu%)_Kvl6XEzSY3q0Q<%Bg6^@c3xMJc}#u_El|%I^+k5p}~;4WN^V?Kk#w*v7gBLbY#R!wn)BYPhC*Aj^4rw|!hbE7x)q|Z^%h$Wnpl3+^ zPol#oWjaN5P-oNOm6z-4;s7Z~lz|3MpeOPm65+ grAVbju)Vf6N{l95s%kbd`RKIcqa0IyWe%wQ2fKa@(EtDd literal 2748 zcmeH}=UdYU5XXNssq7*~Aj$?AqO1lKfv^N*Xb3}QnEHT(B`RTQzANeX{jukNp!H*euaNH>;~4(#IAxckQ3LGH%46|Ql< z5L!DSHU!U0TJI~O`8RAwa5$q8))d>|H(S@X+CNVfdKLn8+t4S|3s8*e^D=L>8 z;ng7hJFRkWwR7YlZzn*B9|FY)P!MGz5+=bk!7%~fr6G}Sx!}s(@ROapaJE>dzhRLu z-_xxweZV%cT~EkofYE0Q&}LFi0gt&<51_F}QUnN2xfm*$Y~sIwyd1*k0*oJOfa2T$30wZ!NN6SMRbdpuR2s{P zQGP1=R0OIHLI}h7<&F{X7zMX_NG=s2bSgO#Q|!i~cwN@MrRpzi@c~g^NgVN4MVv|w zO7!bR_Dd#MFroml4XEb|KpDHD<$V%dy@${X=hr4>0UBkq+vG1o4Z&bQH45VV_~ zBiFv&$lYE$T_Dqi=f^ffWRJ0z?qKx@c6)PVaV#TQ*j~IK(-#$`34AfqFf=J^37-L* zvC;(Ld|4^{U0}1GmMATa<2ZF0DN31iP2tBl`%xRID0w-!Ebsf`;U(zthGHiqXBzfk zNtDa#D8Dwfmrpsn^Qk44hp~~LGM26;u^VDp7&9DJS;Ht83V?k_Yr;03uFkPJ$T{(9 zWt09UD$8@7isMju}-uj6zy3n!UHHX>*x?>&->PfN*i?rU&pPvBrx zJ>MPU%|66~m5D0_D2cTdS59}ZK-*2vQHdRswfm7&k?C=8hh210y}K6n9cTt)%JyCO z*#O)6q=+;Jz#{j~9+=K1O9@x21*TdG6=*%*R@!Y4KS zwdxLrSvy_R_E>}H@E~U)zls~o4o8V&p%bq#A=|yr$Og{5o!=Uc{{T1P9B@c?xn3{; zXr%!}9yK+P8ptTas_2?hsiJ}$AMo-7e_-fLq_3n2|1xMgI1k@GdPxLVdq-yP<~*F! s^X@+DN&42fiu`IL;_^}XXe>wTaC8R$jSj8=aKN47D}x<=ng7rJ2Ay=#;s5{u diff --git a/app/src/main/res/drawable-mdpi/default_album_art.webp b/app/src/main/res/drawable-mdpi/default_album_art.webp index 2ead5c5f9c77947b1ff4932ada868293312f6bfd..6ffd34f027d375daa16f399286293257c95ccb80 100644 GIT binary patch literal 2390 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 diff --git a/app/src/main/res/drawable-mdpi/default_artist_art.webp b/app/src/main/res/drawable-mdpi/default_artist_art.webp index 6b9f55676e4aeb0873c4894e950b97d7a85c815c..c5e115d2233cb906e45eb1587d49cabf191d1f85 100644 GIT binary patch literal 1762 zcmb8h`9B+m0s!zh5=R=h$ml1S1`A3ZK|kUw33UYz6)h2JsF_hm$_SoT&_oc^IwI1# zk18uwnX?#m56R|yb>(@^l)B&kg?+xid_5c;9C#oAz{lR!-P_&F`P1LmSLw|J_*Bv& zMYZEW8~W$M;=!IDLTT2hfhV9(DSVM~-Bh6DpO-aGtydD(_RzT>nx6yXbh5K9cwHIT zldH?6z=*NYEC0Fkr5DdG-2kvFm4D!Bd~mi$Ft)<|<6?Rtpi1ne(Z#0}rDjr5Q|;G{ zwZjvsqnM9lwc4B{gP}w;S6a~7%>5W^XR5v7sMUwq!7XOPA7%$I|9aw*vtB=oJEGo0 zMWi?=Hu)tydY>82$b^lW-+4SYualIGRONn9Otx*)w=Gc|ujC)gawzM#3w%-Cw{F;# zjsedx$W;5d=M(IjFeVZEu<~g+uQoQ&a@6HW-hGh=Qn)poLlYXU2oy?s&(MXwzWjvSnRAExNzwGDzgb2 zw?JST-#6>FuF7aIaxZHJUqWJ;Ym(`I`tb=bKr<5FQp+ix*Ei?h#IJfR#s z_3Qiwr8P%+|IJ#I*dQzB&%;u`|K+s007<3+6URxs*-#8yZ}{OWiuMM+3N=D!Fdl6~ zUNz+MTlA)0vnh+L(Jv2NP;R_t=LKLvr@|yrVk$_^WybwT4-KuV2OYSw&c8f^zE#dZ z4^QKL0BAjsTgDnYOs|4sj%FZq^|HUDIxTL!iSFfv6x)~_lIn{a<*VVQ^3U%AvN`~Xs&^2nieh0k$pp=LL zqq}j+~f)UQ6)8h?C!pqRQOv6;2PX3 znKT|t=9h>plb!+zOg^stV!>rT4_HB)xwhFTd1E%ikHR_JK-stSJ)|StU zJP$n&g$J9wJBA=Wekh)4HKlJxWmgji#OM#gNfwhkEpF8sd5e}^$rs&LQ3|T#MquKC zYz@z&qX=~Qa6hSLe6`p&Xn&cLW5|e-X3#xiAFbhnPYlL&;(Wq)8`FMjIt_KPWNlxU zJvNMgTyQmTH1gu&`9X{wp3lyq9HoyZyH$Uy)&H7Gsoqils=~vVaG5Fpg%mapo^K`C zbE5OlcB@ICq|#cAxpw(b6R+QR+ardxb!Vr?NbIWS*N$`x`G9eayz*OCC>pVTQiXj8 zODeI;%+mdwH)W|xAJX4CSUgl($%13d8+V%nM%Ws}g_ zi>$~+dVEmZ5jPLfrW(hKM_?SXuB%NVWXgyI`|<2k?0k_MN}^nS!KfESyUXFIuax#4 z_|xmvRv`EpfZ?zt{Zf?mF0tR-h9~`Rbj!0Ca(`1+xUE$5&AiiZaE{Pn^^-mp)GSzj zD@v(tMD0JYR2**ZT((Zs=FW^!%3pypJl4VX3PI-Qv`xeK3<`Nd#=C;xOVlG6_^~97 z1$>=O85sgj-#B(tM_R-X$tP$2!nqBmv{w`5lo`MN6k#)|A6}Z_Gcnr-D=5>ZX2c}7 zU5AaZZex9?eLA}5<$=2j*EZ`qyW8a$8qD?0x}xrC@t5k$a)QUV3=D1}J$#}(h+Se& zwIp2&>N3r~$N1WI*ex?Lggus@7?|KS&kow?wlnIjH*F*Rvgrl8QFvQav$nl=*}uZc zNU1{WrZ-Lt_$U@3Wf9^^rW$BU#VMY^*V!hjC3pm~l-UU;AM8-lhu#Y3+Dt4;lheXf znI`%R8?epY>A>&iEv*IjTKt5K6Og_?{w^)Pe0Q2+n{ literal 2410 zcmeHJ`9Bj51D?$-zNmP`91)pFCJ}SQHWM~lj!DWDBD462nw#b>G&yq2HLI^_i%8}O zAzxQHN{)n0DZaH_8+&{If%o(I{`!92=lJRQ?fK<-Tu}&wuLJ<#4nK!+!dWadm%9ZK&a48J@^&*%ic`3B8jAeO48ctUK9u#@&m1I$onOwjWIqlG%y!P z(zVqEtK=fGCn+21yotBVLc}gR#0dyft!)1HuTgPfQDQI3%&N})h;E=7bIbGIg?mxxtyCWpuAAA zqM%Z3#|_N;+Z2MuyEMB(nnzF~L?y5i=xHWHLo&ctpc+nhpy-S9)6$}`$Z6Ysv$PcU z4*NjBF)JPylU6r9l-P?Hy1qR-Mg6=R6BO9pdW;{i#PO)Q+>L znqXAVx-N8ogGIv1f2=a$Op?#~Xfza}Vy;Yl0u_AdU6v|_=NpeJ-Z?8KStRakR{{l6O=`cnw=?#~Q&RRM+pRsR)KxR*F zJ4`7_aofUkAM(`Ki>c06dfjj`9lqMzMFm0&wVfs!o>z3J%z^&9N|K9MQ+8t2m8>+^ z1Ggjt?YC81XrZYI*E`)7ys+Po7%FsD<7%`v6tbvGmw?}s8Yo8L!@zi(iSuwHjRnKT z8)~{&wvs7)Abz(svdCcpn$Ux+zZ{kD!UELQm1InpSHLSLSUo88{W)WVDGmb+;@Dw@ zmX41^CX~bgIlYQosqGF(eN1_DoKHz!rGu-cQmOtfrTh&v8Cpj12j)T$KzF_Is(>l|#PEP)1>xchdkJk+i ztP}IQ_R4iayD%Ee&s=9#Wh;zeqYezy6@tVWB%$Qk=>#d2z(f8HrA;z2v~2FWV<*-7yke>s7z*8U4BVM$hC zTg^ga3*hAYd>NNy6@v0AUGdk!w~X zBoQ<|1w1<1@HA~qS>J_cd}-93Ma(rd2+2(oB~E0jD#X|CzOpxpAy*TqlD>0j}Sm9pO)`|4cmx*&-3M1t=v@XO~ zrVvFVw^(&|#7W5;IY4K!|!0|>MHs&Bd?*?C5c;kaX+?>;^EqjeliI)QrnR(SX2j2C|3 zSOVE;DkE8e!^I9&OS{LR;TB>~&Sn41L1PtNir&cNLKoi}Jj@J}enmjnFXM)k8m003_T zcq9Z-0jdBk@7q^89jn$nsxA&_l$Qv;@hSSMvbDq-Xg;*`F6+J7A4CR0mFK?%+Z^b> j{Vo6A){KtEdb6|b|KtCyS`GmK`+_-fn#%9j^xyDr=(E|z diff --git a/app/src/main/res/drawable-mdpi/default_audio_art.webp b/app/src/main/res/drawable-mdpi/default_audio_art.webp index 8cb8892101f937d588374e05a657d93cbcbbf25b..ad86e0e0c65de8706cf26cf750e83c59af74bb66 100644 GIT binary patch literal 932 zcmWIYbaR`-%)k)t>J$(bVBymbWa~>GYGZJBR>(Yj?ZIE}`KkgZmQ|crXw2#Q&NJ)( z9rk`!6EW@##pv5=hu3A@v@Y8;A?NtE-0GR7|HTD;uAhuo7rpqOQ{nUepZEXd|1EhojQ>&+RA{;OG63b)Vr-z0l>xxlu==j>WPn4aa6KdgP$Prq4vLV5S@ z4W@_t<~wNz751`E+K|rZC6;Ot%KLj&qOWPs>NdNx0V-!VER`~vwNUB;Pw^6oPmX6l^otyB z_BWgov_yQ?-z5_NCdOs_Q{NjPr?B_KkLD{*g?HSe7H$(zYS*D2)jsLEjVCX&)z@a0vsA|3=Kc5X`%jh^o2I`xdCigi!6p4SclVlYSlV~v z@>=sHKcBzSQC_lZUZj^x@6`z1A7K#z7Ov+a^^e3y=)24ZVmTmw7oq=SeWc-;wI*w!mvV?W-29k+h05 z_F2(Zdo|z!PvJEl+f|CIrH+Lj?#j9m%Im&p?cwJRTSR}n>E6aLKlb9Xhnsb8S=5-h zcppxW+v4}*kB~0M{J4`{EcaKWJpZw9Rf0FeE-@YE1*!)ZF-T2$J&{3XMfcVg1uOB@ z(oUCyo^l@gI4xkc#G>Sdw;ZNSd)X8)M?90qjaz8%uLKc2?l0{HHoE6m^LsSzvDnXX zvVO@FTG(2u8y4|>h!rq#oy85;!K&ZdWVV^sT{LV+_hfsh+LwT_Tj1WAts6k zgJ&e{eH3TsdSG7ZTT|By|85t(vUGfK?uzWLKEXZJadU5e5I*31JI~~w;0bqazB^?? zXC|}9WuN)Q@pA9=c~%+9ThilgiZ42M_|M;BbK%Z=^(*S)pYMO!H9_G;`T01r{jciw qb&Diu81FBS{u}W1XGWQZ&n$y$#s+gv{yp<`DN_o;tO3n9nhXF0apNEW literal 1546 zcmWIYbaP{3V_*n(bqWXzu!!JdU|j=luQj=9?3^-&!R1-|JOfaQ1$| zak+mIJq=M0Evx@*hE=0&d3p|l$}FB{Zs-FR60gVw*Y zPWA($dlHxLzr5kN#8!u-?zFbAN92oUYX|VjG0RorT^!eig*j=Nzij z9nrgrNwO*+RQ<5ds;HC*$I$6K(JNj}OpG;tQ?x26v!>#H)4DXIz zj&YT6{B!;t|G$d*>e5YH5BO{R-&`2f_|5+J{J-b_rT^dj|K|TU_20H6xSc)l>D$An zcTe9v`tMjxc;qI3&Xy@Xu{9sx-!I#3^icfro{tCX>+Pf8FvlJH!v6oeZ@A2}n$+8G zPOd*1azHeGQ~LhrlMYVXaAw}WU2ahe9`~lUgxq5F?p$#yJdFFFqnL=_#Mx`alk_9> zUFL3#>##}ND^Pf%N^!&KuEZ8mXG!h0BkD&5ZloW*aJozJU##(&jY%g`&Td#Nc`Cv< zC$lZ(8c*{q#e(IMT9L*&E8E=9PB=DeVIU}!tj`LZo~0OUI%Q>>+Es%EQfZ-wH)SM$ zh!n}?u=~8|>w)yJEoMJ_y00*?zM4C40~Zw>eTyMRQH8SyJye>deoKSTw~vu#MyF*-3L+4|SS7 zsqj~}Id0c+(V^p9op@58LF_l(LuCvhS9A_WvK*{Buy?i#Q`z$Da88!DyY!czOXj?@ zG@tLSoA4gv^>b!&2pl-P?Cy^h>J!54EH}*eGU$*0a?5@9{0Z~+K3;h=#i{ycYx*`L z&JX(@P1WbG(R(8J>Tz}c|Cg)Or!AO&bLZcW;q9@ROBfD&?SB4ke*Kr4eRl#y{AL+g zY42aLWzjAhbwdxFnFTE?O<@A&T?H#928IGhhPjMdGE6c|b`w1o`l>EbR#M<#*dWB2 znfI_fQQCp?4fFk+IqmyyTJqO!Dw6x1^2GMr$rIIYCr|i(TV3(}Hb3W4>ERVDA`A@w O{@>$RB?Bzg@c{sTry*AW diff --git a/app/src/main/res/drawable-v21/widget_selector_light.xml b/app/src/main/res/drawable-v21/widget_selector_light.xml index 86c53d73..83aed83c 100644 --- a/app/src/main/res/drawable-v21/widget_selector_light.xml +++ b/app/src/main/res/drawable-v21/widget_selector_light.xml @@ -1,3 +1,3 @@ \ No newline at end of file + android:color="@color/ripple_material_light" /> \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/default_album_art.webp b/app/src/main/res/drawable-xhdpi/default_album_art.webp index 05cb419efa5960a34b5bd3c7038fdcb0467d5053..0c50842cbd27e9096e75a5b7c57dc5f02f4db2c4 100644 GIT binary patch literal 5526 zcmchbWl$7=x5bqP0f_}kL0}0Hq@2TvZlZ{6-tb9lHFe=219?z{xizIF|umI#n# ze;v9cIwW{jbg)hN0H3-tS0u}AL}?k~XfhKm2K1OuU_;f>InZIG`UBIzTQ-jZ8-Gd^sfRn=6 zjBiO!;4QQL{43t*gV@Bf-QxVk{v%h78ycl)PDkY{o4xJcizwGFk&kHy_-fzEodSM{ zedxwgv3)@x`4@!5Z+E#f8CrJam1{{~b~yx4*$-ptRm;xacDV#-+YgttpAFWu=&chM z*;jImrq$`3duq@X=^z~@`E3ruxF{x!96N2A{MQD5$xW^goD4Mq1ANUQ)r*f(G-V7FUkls z&uGtI4l=WF*a*3k9T`dv_w+V%S>}Z;x1;3yzKCc=oK)PO_4Ij(%hSi~U&^sL45pX7 zzZfS3z}3JG7PWjWfff#*fe6Y|XBLaa)9jBUZ#Kt177AvRoKB9!JQf#9b1}=3ya?Sg z01gVcZ?ivuyA4KQu`*Qit^HJhTVxVZ^(W2FP0`@%if^JiG3CoY{SwLFnBuIDbtO?< z0R4Vh_-z#9D>Jm2)wMo-D{VopdP`@ zq81Ir4_?YRk||2g@LDSXH6F3Y-KM;u2y$yWo=~*pVGUWIk4X~hU%SuUi%1e7q1n%A zYW>(h@w%%Adlr!->BMj$q{Jw5ZEs-~y|b*t61r{rE!dSYBIz|rWudg&PJR-&Ir97` z$rBm22I9iUOJ^xDh>yCf>WS+8Ouh8d!<4Z+y-mC~D6QDBo~4}+OG>;;kl0JV1K5`Wu0}quqssFs@cQLrd_<{O~Gf!{Umz{%U)sf&(B=P^P$Wnoq~*TKcYj)Hcj76E$&^a@qGUaM4_tw(lKdC zXxrwjFRfK{+_`&-VKmv=0oKuva}u`X({i{FU8F|qu)YAXG>C)vV(4S&W;aAq6dYy8Gc5wzQTWL0$fztR7H5 zIO7zi>6!ca%;t;Lc6Mca(}>>Nahiwl2BI%8yjxVfBAIcLB_GNkl{aD%^2$dIo8PvN zt2+KTKuh=C{)ha9IPNM~oFH9ax?W^Kevbi}4(yL%{4Hhbzn;X2&FvA9>be$KV%aj*%>A#D0VR*5$>G)sq zSlq*cBl|8q+Bn+qr+Y1@u;ms}cLfM>q_`;?OG9h~2Jb@SSR~Msm*QYJ*9&MZL_xOy z(*uRzBHAKWS23hc%)?uk0(hl<=OeUqK%|SrDgue(qz0H=Dsm@S28u^i>A?wikY~_u zF^nSc$}Q8ubHW_ET{s@H#!!Znbqj7gzLZNw<(hsSAHGIY)}K?`3+8X1TtR_^7Oe{$ zT(S8@c3wFrr}e|HQAhbazgMCP>2I<;bSSNIB~OSK2N=bO>lkvGRCz|j#U|*5`33P8 z`Zgn28&d{uY=jJgA=8}`Lshti(ZYtEIW;*`pHZ;FRvwR1NK z_`vM>X8Dg&Y&2fReqx&aW5ni5;N$Y%1I@ zz-8NBhV#BI#a5s-Dt+wnWjCS4_o7pu7icm}W>zhm*-m;dAJIB(o-}>p-U{n#@1Lg4 z4Y{+>Eq?-!yHB(k3u`bz=2Js0rczD+O0VdsysYWEvFkKH@qI5=tsR zv03qE=>271Pnc*z7!JFU6mP<$sX#SLu*A?zW#R*IS(7_DrUexm1-GuRVjN~VMB}kv zQTQPpDYJ=Q-hr{JKBTGkg$yM{Mtpr@&riIXeS&_h?e*QqzOLD#;^v-CcEKS_Bod(~ zp0#YJw3qS-Co88T0qxM9nilFf0eBeyxTk*af`42KfalTga_42PrvK^0pC` z?CTFF^TB?H;{*BZFh3tLac*BU|H&d8zjb8=f?uRRNTD%6h z;_kE6FZ_lb#>LN#vp}2MLOgot7X>EDN8d8Y=YhKz;UWNPGeIYDez9i%?^3MlWV)J& zgBd~t=SClX9OG(F{%?!fM{3}T?O}^NxgrAg-EsrMJ)Dqv>u{AdV~ZM_ja=%g{*1<( z{N&@_-*0H}Vs$l4=&d5O0h5?YUN-GD&mwAKk{O%J)6Q+;6e{QyA;A}4_fbLimiNeW z)McHw+sCT`7T0%X^S%=7i8dvAyNZUaE9)mQDY;emEC|xK z-M2{|{0kp;o(4VC4Qon+xW(=S{7J&*+fM3>&e7$TS+MR0&t{f3wi(~*cVBasHnwOl zCQ3HQ0ZG6sQde_BjjrGxIq~T5D*yJcrbX%$X1$1ftUIO3`m}^`)sw zR{rbZG>X-!2!xl)?&;P^?qK2O3p6xK-Q^a~GLqz%h=E#|>-ST-vO%DE#&60@I@MLx^%$u`2S~nd(}WP{6x9=S36}1!P=Ome^O~wA|JFE15Q6AVL0|`?_vL z$gnfg;Wl|jo36#YJ)!m-e>riB3<7PEz2}Z{Bg(en;8ub5chjFViV@z2(LOci>GW9Q z_FlW^{be-X8lw#f3ZDczPm}l(+`PY!A#5~#cKP(uCl!`vddb8QTIVx;LgIagv)T&yz2w@ zpnipwt9Kmty`bD*0sdSTg`sITsR`tXA7_>2W&1KWjHJntL6PL-NdE5V?J)m%fV9UT z_}=E2ce5=ns&U1lsPzN4`))^<0=#PvP|Rh{Ca)2MsWuO*S2FW*n;xEO(<;#40!xSF zF`h?#aG3`EY|}FL+XBlHN{U@8O|(tar6wla&3n0=Z4iCF?KXlc-q*FKh#85Uj55wj z(L52K&=_#})e2AOH0Vgta1}doI|SdYETgbU##J|=yCSkjzs zW^7US?h4ss^1y)LpEeswvdfqET4HwuE%tW_z$AhCg5LH&tIbX~inX5B!Mom0`%yh( z3Ae46!=ph3>A;nvmt&>miMMYT8ybR*KoS@4`8+C41A{MT@uf&l17#T=`*`dJLywP> z_pk@omRsNN?$iNT;=nt{1Fo|xfqx^sA$WbRcIYl*&h5bbGBM#cb#>4^m_Ux=biIQG z(3#u4>={FA>vv~+c}R$V%FO(?0FPAg$t>2iZ(X)y^%Ya(dC;7|T%~((f_SAklVINg z)=!b^$E^ac(px`pF$_p9oI^>-$tjfsrx0m4f{%24i^1j(X065ig%4ysh+Wh`TU2vK zTTKbmQ9~v?{}sQAK7c12Sy31pNFMy85R(Yy$G8pTj2QJlj084JokAw%mj;JmCdmsV}4T8lG8Yun*l?)yfvkz0`lq4(d6SjN+!)%Eaf zbT1Zml(@)k;{o{@0Ct$LXdAr=sl5rv()QZXQ%>PK-BnpH-uvnR(IOnt=X~flMws#M z-y)#TL|J{UC7URy`zO{Ab27iSrO)>j0`NV5+OGP%t0+t)yHk{lWX?d2Na`{jRx})T zG-k6V5w8#v^*znWJ?+A0q4}aHkrAuF68LtQ2^t8K1si_aFjB$~9r^Qi{4v48#lDrX z9O~5vcwQwj3H@cNVMO*?GPe4pn)huost5|e)T81?IQtQlqJyJiq3p{n(sA`Jq3j-E zit8lrnAqs8G$|-_dN}^h>(Iwl7N*kQ0fgdJ^ZjR!b(58sg$ZcvCuh!_5S1{s_WO&s zJ?;2;X95Fo^8mbpv&NF}0Iev^ssbrceU%(w2dZRj@`hQ3-Uh5rzzE0{>W>YHkmQh4 zjHK6Mjw5@dM{gabQ=33+B*@umZw=FrG(3L5OxrKy^*!VWg5N|Mlo%91=~+>Fuk*{e zylU-VBb&zd>N0!mEXVnxm&|(jr5m0Sa^#Ts?J)l9{&Wd%IZI*>1i*+i&ispcu6} zt73l9kI2TRFusPUxsA$Ax6f4)H@1CYZZJZteH%3?`P6~%gt>x?MSfORvgURX@$ION zSmvsD(NfxDEXLmGUe7K3dzVIU%!p>QE%JuI91JzI+U{;!E`av4JyUrpB<1{ZY9z@v zJhAg=qzwNrX>(C6t_CNnyz!~?sv!dN4Q)`;qM|XfUhqDL^5T1MtumE`jcoh1h$LHO z$dHO|OQ*ixbN*)nmzhbN(;R}w-H=IXd(0%RSdqO4_*bMVl~im#k z=}Ecv?ZH_8&)wNQv7?;emJ4#3yxhRHOEVimY0#Bd{oM8EtGm&?nwhp3Q1?6P%|X5Y K(7^u(QU4e3cK!SS literal 8320 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 F{TJ3O-qrvB diff --git a/app/src/main/res/drawable-xhdpi/default_artist_art.webp b/app/src/main/res/drawable-xhdpi/default_artist_art.webp index aec9f594de1bd3a213c70cd27e3de345d4379b73..d519bac071b38883cb883f484e57db98f00c64d0 100644 GIT binary patch literal 3732 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 literal 6056 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 F{{!m^YZCwf diff --git a/app/src/main/res/drawable-xhdpi/default_audio_art.webp b/app/src/main/res/drawable-xhdpi/default_audio_art.webp index cfea182a4088c240c0753a6ff7fd224760eae180..7ee8cdc52ee1600af1e73e84cfd75fca5c7d54f3 100644 GIT binary patch literal 1964 zcmc)L>pv3;1Hf@(BrNL?**qbHYACi*Y#3{HmfLBrhY({%IdNL$8qPSW5OYMX>EU71 z+(wqma!HA~Y{SU42ccYZ&z|!yJg?5@^L_FA4}LE8SZwJL2?;kl8z)yMGeXYaZG`Lq z0o*W}HiMr+c!qzkN0WfL>r38>qo5{R=C{F9{r}F-a z=`t=6D;2TA#^%JsoH3n1TY^N)exZ2xpQSO*e81o@y}G=2I2|$RU9kLLlWA){l;`8N zo7#Zq^k}g*t~fxK>5g7fW=QAq+6I))`INlYAjLaWn^l#20cnRjpQOSt$mQvqa>J6B zVOv{e22Rkpz!ly;7$)#n5=n)V@~gF=e#T3%8uLsi#LkB^pJZyPA$h+mcF`6?MUpAs zi6d{IU=n?_<0z2hr%ffTQZhkbH;aY|@2*8l`Di8gHb3y*4_y_4Z(pq)c=e#i%@k@h z>-rRQ{b*7434$e&N8XGFD|4;0f#IVk@)MA;H9SspPgrEO^NGyH1L%d$ZhW zIaj!~4tEg)MspuZzkZ1b;L|ih+H*x;l=cC+kaR$xw45X+jGF(7966 zQXCnV(bw;zo6pVH%P+RTUut(wzb1pk?pT%$`M9VR%*(!=-}q@eqsz%t`()vV{RvaR zuEq1&K(zI)a&BiP-;X?c|mn8)5SY!|EHC)xC1IT@y5?zu1C#p zcdl3dQb{aGO+&tGtsNLeb!r;FZn@>QD~?mN_0e9#(OwYFs*l< z-MVU`%{JLlQ}Q|$d%q()Nh8EQ?0DQnDIy8Y<{#`toUN0azU2_CD4~496A<5(q#|8p zb%m5DVQX}{Qc1Efbs3USb9yYPh@8=jNpID?AfM2!GJ<|P^`;GB9qizHL-RAW^E*~Q z+OP_3tgJe$uJ9eV^yvsDKz=DF{I0jVpQc>B9Z^fC1uRfehW%VIbj0qksmM?^HSTE0 z@ke`?{O@awyN#E%998MAly=U_xDu6MwfCz!+2%_;?9sWmU%sh2XPqx9;pS>Sk4;#7uXv&H z22hys1T5MB4lmiH9QU2KW!a@S>&2@-*kZ3CjLxYrs64tmJ47&Gl`u?t2W1Sfrv z)Y{|yd;6x?ZKR_4@wyo~_9fo$X*~L*d3ns^!9KHTab(}kxGEur z6kpfYHooNXf$#A)J WRvr_(w}lpO{7u~O&wZ(NQ~H0M-7d}m literal 4188 zcmeHK={FmQ7Eee?G_llHG3}sQYdVymOe+%mUQ{DW)z(TxHx(LmY_YaY7qzwa7DF_) zSWmT4Wh@avN<-0N7&|H2BF}s8FL+<(%?J1V&b{Y%@3(vIy}xr^Y%DF^Bmsa67HDU8 zXCtf_007vd07KBfVP@}a-6aYD027PziHepsHtD8~M?g{!r!nHEC>KVq4>O3W$$zyj z+}mx|Q8|HXHL@?v)MH^bJG38Z=zA4KoY2Tl+r5FWuR}N$nV{oDNSkj(>~1iNAAR<= zm?w%PhO+CkP}!7-oKaJr z`dm)yGa>!Tk0#!ZE~K%6ch1K=IQRO`!0>N<_Vin~iSLJ1Ts!*2u2%-mQE0bGox(Q| zCc$r4%k0DFjr>y`wWm;?tMZJMhH)TaN#ikXr$KJ;_mjhGuIrBGih3jBo9mN3HSGop z1W~@5IgPwL zHZnVuS*x`R_0E!FEUOKFjU|q1TUHt~zB;{`hVm3iU${oRZIU6rQ6;RyuN28-Tr<+` zjtIK@Ym!Hl_M2Nh-!*|DsEU>+V0Wo`-Bg_=kqTFZ>k{76HIkPmhw^2hEx5-*^33z* z(6+1T9lnvt?ueVi7_HWye6QB2in2iEzr>b`mP?z3#ttPYMf%9fzEj5@2T1|6|$SyGmucNqf;7BX9JC~$Sg$1-rHP6BZKc^^-rGfil>=e&Zk?S~y*KHZ7w6ofQ8i>Nv=(O0ZSn$5 zJ2b$qrKL+gv*KNB1GRlELUUnss^{)&Qt5<(% z+uV4%?1wjWj*ko(&$tx%fD{$N*78hSjS^I0?~^JM$-(!2#05EL%oq+Ef3b_u$=Ky* z(}phc(HC(#EH2q3BjK8`6l3O{n+OB>oPJvnE*AWW_*B&e*6tCY4z1F;+?D5(uDpJx zTe=7iYaI;lC3@u9jmX0^KtGV#NymiYgAf%@*TrPuODGVt&?w<(6{kowk?& z7s9aLi-Od2k&ZI%gx`y|5oO3UI%h(^mJ-5+ht*NwTsXH@~wiZXjmrZ@Vb5-S`NnySo5EOf&Nw3Zm4upUZv}2YicX zfKcbr>p-fBMvV%f@ZiHSNug`03&%hQ%;nh3-ucULqiB<_i;^tW|OQE8Y{U+xQK$4q}r}NPd z=W))<;M6OiArZ?)8(l9c__dTd$WKUXja;BrsCuyt^NWE(yB;7}+=8Db+30{a(nPU9D*g1lrFL^X zE6T;@33D$KKwUY#Eltsch zGxIg@?}S6XNf#usB-MnK@`Q;yZeU^1u$~I|kpC+&pQk7?XCoHGE3zTyC`~M#S`2=Y z->e(r`9~t?)3j91DKhx=dSCDy83qiW88@iS!ALGWt9l-wRuJyli|-;z=HyQf_Cv zat+q}!vYpD>M~+cJ8P4@oT+y{gsRkN!MI>&4}#7Ag#VJi*$eK8?Po%F(-KkDH;?}CpE|SgM<;pl xF?Extro7B>#O#;%+p<3n`)ja&9rmx{z8d^PMX~|_*cE&NmmW~v`|1B~`xozh+9d!0 diff --git a/app/src/main/res/drawable-xxhdpi/default_album_art.webp b/app/src/main/res/drawable-xxhdpi/default_album_art.webp index 6f679760d59f61f8149d22455f6fc48abc4f2fdd..0b8fe94ac875de62e8dcdd4058a2d4a46e6866e0 100644 GIT binary patch literal 9048 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

Pz?a1S7%%L}i}q7`4J=oNO`U(G37ChX_nO>gT~ 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 bWLFPHMcrQf#}vWciTeNeuNt`Ha=-U~Q4-3% literal 10834 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 H|LgT%CGNeU diff --git a/app/src/main/res/drawable-xxhdpi/default_audio_art.webp b/app/src/main/res/drawable-xxhdpi/default_audio_art.webp index 26b8aba93d6ee69b1d22e41613d3cf3eb84046f8..4688f9dc340b9a76a2157ed3b7eaeceaff91606f 100644 GIT binary patch literal 3252 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 er3dH*^%KWJU~y1Z>j#9|7k!lA^J~GgDBJh literal 8136 zcmeHMS5%W*7LGI%nh+v*<Y(;Gy^0MT1dQrbZJJ4peP-=2t*)1ARtmiYNYqj z4M;~o1V&McbWrKNDqJ$S*1XQV%)>lP⁣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 P|MB0D{~rHyBk;cffV!{X diff --git a/app/src/main/res/drawable-xxxhdpi/default_artist_art.webp b/app/src/main/res/drawable-xxxhdpi/default_artist_art.webp index aef914a89d636e96f63700f3cab10802a33cc972..1acef0849db08caa5e9382a2cdb3a1d4931fbaaa 100644 GIT binary patch literal 8084 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 literal 16950 zcmeI4RZv_(*RCOi1Og-hg1Zf_g9mqaclUwdF2NamupooG5AFnKaQ8rh1`kfqKVSVf zr_SA}`fg4YUAr&3cJ1BOtJdyb>wQ*jHCZVs7BK__ZAmc|Efrp!cL)dwAOCeHl>c0! z3Mw-06bJ~2HPiq_9me~&mvNC}*ip`_QgMY(tJy8Szlbp3tu?7SqVxEKW9n#R^wk5H z86HcBBA;vqWN~x(oX}`Vhi`qkAzW_~7c4(qrhEi@&vP)ydtiRB9S(m))S%%fjWS<5n!xkl4hLnA~Fg!yri&#Ii`89y+yD zcquHoM=h7b6}V=a5ILQjSb;ZWyw)l>xg`+LGBFVOq#X48_}oFi|Lmlrm5Qu~876Wz z3Z#ztM3w*coP7FsR5+z-E;T+ti2OT>S11IMPyzAN)lI$6dAJQY;R6n_d)8n+<{Oph;J@exInVz*>bbo%&C>25F6S<{^-9cF-(G%pfAG$H9_KVW zfp6CNYIkX_*Qw_G{FJ%FyGsE0G_GyPJcM=Xk>KEP+77(A&wk*+tBbyQ(>9^i=%!zhO(R6X?kyU;abCY@^<%?nI&YyB%O9d^Cv2jwU4#0@y9p1RMvoh9D)3an=YT#L<~%>zh!H3 z&^xl}S6ThQ(Qe6Bt&{2}5vovuy&0epQli&++{8^AnX52zj*W+m%v*1gk{xI%dcURU z%h3Fh$_pp$EO!xKv&hq|kb7dN=2$G%P>gE#Gpthcr((IVmCHN$)XZ0<4D~wX-Ok`n zS^v1`{Y5D~1Lvkyvp^0b63ri?Q7DAV!=EQjvg$!SQy@vB)t|CUlw2z6T%w%BprPKA zHyrsUWdf}JDD${>>@+mY6w2O2c8vo zuGiPJQ_pN!xz|&_YphSyDza5r192B|a7B%hOn;Npf-2=1nI7Oa-^&;?Y`6)y7#R}c zF18z$GtKWp<1gvuftvxIgaB6swGz_CNPANC_+6-a zmmHtn#~XoMVnyCk9@%-iBu|x@0zwRMbU-x$jnQX%TdkOtenn*lsronu<2+nVJmQqg za!KRpihyFA6boodmMWM9Vi3{OU# z|1xuxs*mB$=d!b}GR_Bcm;p*sa_QiI)8wXjg0DqT7*yIz1=YTWOM=vq^*(Zy%>}K)S9Fm}gDg7b5z9X{AtL{V)c#Np;tvC< zA`*UVs(i&s?+_OHR1a`)QFw;S>PO#U18h�_6sd8Lvu|*1A*!S-`6;cdmwOR&zO@ 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 literal 13032 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 Nj{k{ZZ2!F(_y@NeuDJjJ diff --git a/app/src/main/res/drawable/circle_progress.xml b/app/src/main/res/drawable/circle_progress.xml index 8cbb3008..d7949891 100644 --- a/app/src/main/res/drawable/circle_progress.xml +++ b/app/src/main/res/drawable/circle_progress.xml @@ -12,24 +12,24 @@ ~ See the GNU General Public License for more details. --> - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_app_shortcut_background.xml b/app/src/main/res/drawable/ic_app_shortcut_background.xml index ff13635e..5c0a5a68 100644 --- a/app/src/main/res/drawable/ic_app_shortcut_background.xml +++ b/app/src/main/res/drawable/ic_app_shortcut_background.xml @@ -2,8 +2,8 @@ + android:viewportWidth="176" + android:viewportHeight="176"> + android:viewportWidth="176" + android:viewportHeight="176"> + android:viewportWidth="176" + android:viewportHeight="176"> + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" /> diff --git a/app/src/main/res/drawable/ic_bookmark_music_white_24dp.xml b/app/src/main/res/drawable/ic_bookmark_music_white_24dp.xml index fa10a8fa..bcde9ac7 100644 --- a/app/src/main/res/drawable/ic_bookmark_music_white_24dp.xml +++ b/app/src/main/res/drawable/ic_bookmark_music_white_24dp.xml @@ -2,8 +2,8 @@ + android:viewportWidth="24" + android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/ic_card_giftcard_white_24dp.xml b/app/src/main/res/drawable/ic_card_giftcard_white_24dp.xml index 880b4f5b..7063383b 100644 --- a/app/src/main/res/drawable/ic_card_giftcard_white_24dp.xml +++ b/app/src/main/res/drawable/ic_card_giftcard_white_24dp.xml @@ -1,5 +1,4 @@ - - - - + + diff --git a/app/src/main/res/drawable/ic_drag_vertical_white_24dp.xml b/app/src/main/res/drawable/ic_drag_vertical_white_24dp.xml index 402b4b9e..1b9e7c30 100755 --- a/app/src/main/res/drawable/ic_drag_vertical_white_24dp.xml +++ b/app/src/main/res/drawable/ic_drag_vertical_white_24dp.xml @@ -2,8 +2,8 @@ + android:viewportWidth="24" + android:viewportHeight="24"> - - + + diff --git a/app/src/main/res/drawable/ic_edit_white_24dp.xml b/app/src/main/res/drawable/ic_edit_white_24dp.xml index 9ba07137..3804d9f9 100644 --- a/app/src/main/res/drawable/ic_edit_white_24dp.xml +++ b/app/src/main/res/drawable/ic_edit_white_24dp.xml @@ -1,5 +1,4 @@ - -