Working towards single activity design

This commit is contained in:
Hemanth S 2020-08-11 23:59:44 +05:30
parent 31534769a8
commit 3ebf777d7b
87 changed files with 1908 additions and 2423 deletions

View file

@ -34,7 +34,7 @@ android {
} }
signingConfigs { signingConfigs {
release { release {
Properties properties = getProperties('/Users/h4h13/Documents/Github/retro.properties') Properties properties = getProperties('/Users/apple/Documents/Github/retro.properties')
storeFile file(getProperty(properties, 'storeFile')) storeFile file(getProperty(properties, 'storeFile'))
keyAlias getProperty(properties, 'keyAlias') keyAlias getProperty(properties, 'keyAlias')
storePassword getProperty(properties, 'storePassword') storePassword getProperty(properties, 'storePassword')
@ -120,6 +120,7 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.3.0-alpha01' implementation 'com.google.android.material:material:1.3.0-alpha01'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
def retrofit_version = '2.9.0' def retrofit_version = '2.9.0'
implementation "com.squareup.retrofit2:retrofit:$retrofit_version" implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
@ -160,7 +161,8 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
implementation 'com.google.android.play:core:1.7.3' def playcore_version = "1.8.1"
implementation "com.google.android.play:core-ktx:$playcore_version"
implementation 'me.jorgecastillo:androidcolorx:0.2.0' implementation 'me.jorgecastillo:androidcolorx:0.2.0'
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4' debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
implementation 'com.github.dhaval2404:imagepicker:1.7.1' implementation 'com.github.dhaval2404:imagepicker:1.7.1'
@ -176,5 +178,4 @@ dependencies {
def nav_version = "2.3.0" def nav_version = "2.3.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
} }

View file

@ -12,7 +12,7 @@
"filters": [], "filters": [],
"properties": [], "properties": [],
"versionCode": 10438, "versionCode": 10438,
"versionName": "10438", "versionName": "3.5.650_0810",
"enabled": true, "enabled": true,
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }

View file

@ -21,12 +21,12 @@
<application <application
android:name=".App" android:name=".App"
android:allowBackup="true" android:allowBackup="true"
android:configChanges="locale|layoutDirection"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:configChanges="locale|layoutDirection"
android:theme="@style/Theme.RetroMusic.FollowSystem" android:theme="@style/Theme.RetroMusic.FollowSystem"
android:usesCleartextTraffic="false" android:usesCleartextTraffic="false"
tools:ignore="AllowBackup,GoogleAppIndexingWarning" tools:ignore="AllowBackup,GoogleAppIndexingWarning"
@ -105,18 +105,13 @@
<data android:mimeType="vnd.android.cursor.dir/audio" /> <data android:mimeType="vnd.android.cursor.dir/audio" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".activities.albums.AlbumDetailsActivity" />
<activity android:name=".activities.artists.ArtistDetailActivity" />
<activity android:name=".activities.playlist.PlaylistDetailActivity" />
<activity android:name=".activities.PlayingQueueActivity" /> <activity android:name=".activities.PlayingQueueActivity" />
<activity android:name=".activities.AboutActivity" /> <activity android:name="code.name.monkey.retromusic.fragments.about.AboutActivity" />
<activity android:name=".activities.tageditor.AlbumTagEditorActivity" /> <activity android:name=".activities.tageditor.AlbumTagEditorActivity" />
<activity android:name=".activities.tageditor.SongTagEditorActivity" /> <activity android:name=".activities.tageditor.SongTagEditorActivity" />
<activity android:name=".activities.SettingsActivity" />
<activity android:name=".activities.LyricsActivity" /> <activity android:name=".activities.LyricsActivity" />
<activity android:name=".activities.UserInfoActivity" /> <activity android:name=".activities.UserInfoActivity" />
<activity android:name=".activities.SupportDevelopmentActivity" /> <activity android:name=".activities.SupportDevelopmentActivity" />
<activity android:name=".activities.genre.GenreDetailsActivity" />
<activity android:name=".activities.LicenseActivity" /> <activity android:name=".activities.LicenseActivity" />
<activity android:name=".activities.PurchaseActivity" /> <activity android:name=".activities.PurchaseActivity" />
<activity android:name=".activities.WhatsNewActivity" /> <activity android:name=".activities.WhatsNewActivity" />

View file

@ -48,13 +48,16 @@ object Constants {
MediaStore.Audio.AudioColumns.ALBUM, // 8 MediaStore.Audio.AudioColumns.ALBUM, // 8
MediaStore.Audio.AudioColumns.ARTIST_ID, // 9 MediaStore.Audio.AudioColumns.ARTIST_ID, // 9
MediaStore.Audio.AudioColumns.ARTIST,// 10 MediaStore.Audio.AudioColumns.ARTIST,// 10
MediaStore.Audio.AudioColumns.COMPOSER// 11 MediaStore.Audio.AudioColumns.COMPOSER,// 11
"album_artist"//12
) )
const val NUMBER_OF_TOP_TRACKS = 99 const val NUMBER_OF_TOP_TRACKS = 99
} }
const val EXTRA_GENRE = "extra_genre"
const val EXTRA_PLAYLIST = "extra_playlist"
const val EXTRA_ALBUM_ID = "extra_album_id"
const val EXTRA_ARTIST_ID = "extra_artist_id"
const val EXTRA_SONG = "extra_songs" const val EXTRA_SONG = "extra_songs"
const val EXTRA_PLAYLIST = "extra_list"
const val LIBRARY_CATEGORIES = "library_categories" const val LIBRARY_CATEGORIES = "library_categories"
const val EXTRA_SONG_INFO = "extra_song_info" const val EXTRA_SONG_INFO = "extra_song_info"
const val DESATURATED_COLOR = "desaturated_color" const val DESATURATED_COLOR = "desaturated_color"

View file

@ -1,9 +1,9 @@
package code.name.monkey.retromusic package code.name.monkey.retromusic
import code.name.monkey.retromusic.activities.albums.AlbumDetailsViewModel import code.name.monkey.retromusic.fragments.albums.AlbumDetailsViewModel
import code.name.monkey.retromusic.activities.artists.ArtistDetailsViewModel import code.name.monkey.retromusic.fragments.artists.ArtistDetailsViewModel
import code.name.monkey.retromusic.activities.genre.GenreDetailsViewModel import code.name.monkey.retromusic.fragments.genres.GenreDetailsViewModel
import code.name.monkey.retromusic.activities.playlist.PlaylistDetailsViewModel import code.name.monkey.retromusic.fragments.playlists.PlaylistDetailsViewModel
import code.name.monkey.retromusic.activities.search.SearchViewModel import code.name.monkey.retromusic.activities.search.SearchViewModel
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
@ -28,19 +28,31 @@ private val viewModules = module {
} }
viewModel { (albumId: Int) -> viewModel { (albumId: Int) ->
AlbumDetailsViewModel(get(), albumId) AlbumDetailsViewModel(
get(),
albumId
)
} }
viewModel { (artistId: Int) -> viewModel { (artistId: Int) ->
ArtistDetailsViewModel(get(), artistId) ArtistDetailsViewModel(
get(),
artistId
)
} }
viewModel { (playlist: Playlist) -> viewModel { (playlist: Playlist) ->
PlaylistDetailsViewModel(get(), playlist) PlaylistDetailsViewModel(
get(),
playlist
)
} }
viewModel { (genre: Genre) -> viewModel { (genre: Genre) ->
GenreDetailsViewModel(get(), genre) GenreDetailsViewModel(
get(),
genre
)
} }
viewModel { viewModel {

View file

@ -1,113 +1,51 @@
package code.name.monkey.retromusic.activities package code.name.monkey.retromusic.activities
import android.app.ActivityOptions import android.content.Intent
import android.content.* import android.content.SharedPreferences
import android.content.IntentSender.SendIntentException
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore import android.provider.MediaStore
import android.util.Log import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.SubMenu
import android.view.View import android.view.View
import androidx.core.app.ActivityCompat import code.name.monkey.appthemehelper.ThemeStore
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog.Companion.create import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.extensions.findNavController
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.albums.AlbumsFragment
import code.name.monkey.retromusic.fragments.artists.ArtistsFragment
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.fragments.folder.FoldersFragment
import code.name.monkey.retromusic.fragments.genres.GenresFragment
import code.name.monkey.retromusic.fragments.home.BannerHomeFragment
import code.name.monkey.retromusic.fragments.playlists.PlaylistsFragment
import code.name.monkey.retromusic.fragments.queue.PlayingQueueFragment
import code.name.monkey.retromusic.fragments.songs.SongsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote.isPlaying
import code.name.monkey.retromusic.helper.MusicPlayerRemote.openAndShuffleQueue import code.name.monkey.retromusic.helper.MusicPlayerRemote.openAndShuffleQueue
import code.name.monkey.retromusic.helper.MusicPlayerRemote.openQueue import code.name.monkey.retromusic.helper.MusicPlayerRemote.openQueue
import code.name.monkey.retromusic.helper.MusicPlayerRemote.playFromUri import code.name.monkey.retromusic.helper.MusicPlayerRemote.playFromUri
import code.name.monkey.retromusic.helper.MusicPlayerRemote.shuffleMode import code.name.monkey.retromusic.helper.MusicPlayerRemote.shuffleMode
import code.name.monkey.retromusic.helper.SearchQueryHelper.getSongs import code.name.monkey.retromusic.helper.SearchQueryHelper.getSongs
import code.name.monkey.retromusic.helper.SortOrder.*
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.loaders.AlbumLoader.getAlbum import code.name.monkey.retromusic.loaders.AlbumLoader.getAlbum
import code.name.monkey.retromusic.loaders.ArtistLoader.getArtist import code.name.monkey.retromusic.loaders.ArtistLoader.getArtist
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader.getPlaylistSongList import code.name.monkey.retromusic.loaders.PlaylistSongsLoader.getPlaylistSongList
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.AppRater.appLaunched import code.name.monkey.retromusic.util.AppRater.appLaunched
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroColorUtil import code.name.monkey.retromusic.util.RetroColorUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.afollestad.materialcab.MaterialCab import com.afollestad.materialcab.MaterialCab
import com.google.android.material.appbar.AppBarLayout import com.afollestad.materialdialogs.color.ColorChooserDialog
import com.google.android.material.snackbar.Snackbar
import com.google.android.play.core.appupdate.AppUpdateInfo
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.InstallState
import com.google.android.play.core.install.InstallStateUpdatedListener
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.InstallStatus.DOWNLOADED
import com.google.android.play.core.install.model.InstallStatus.INSTALLED
import com.google.android.play.core.install.model.UpdateAvailability
import com.google.android.play.core.tasks.Task
import kotlinx.android.synthetic.main.activity_main_content.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import java.util.* import java.util.*
class MainActivity : AbsSlidingMusicPanelActivity(), class MainActivity : AbsSlidingMusicPanelActivity(),
SharedPreferences.OnSharedPreferenceChangeListener, CabHolder { SharedPreferences.OnSharedPreferenceChangeListener, CabHolder,
ColorChooserDialog.ColorCallback {
companion object { companion object {
const val TAG = "MainActivity" const val TAG = "MainActivity"
const val EXPAND_PANEL = "expand_panel" const val EXPAND_PANEL = "expand_panel"
const val APP_UPDATE_REQUEST_CODE = 9002 const val APP_UPDATE_REQUEST_CODE = 9002
} }
private val libraryViewModel: LibraryViewModel by inject() private val libraryViewModel: LibraryViewModel by inject()
private var cab: MaterialCab? = null private var cab: MaterialCab? = null
private val intentFilter = IntentFilter(Intent.ACTION_SCREEN_OFF)
private lateinit var currentFragment: MainActivityFragmentCallbacks
private var appUpdateManager: AppUpdateManager? = null
private var blockRequestPermissions = false private var blockRequestPermissions = false
private val listener = object : InstallStateUpdatedListener {
override fun onStateUpdate(state: InstallState) {
when {
state.installStatus() == DOWNLOADED -> {
popupSnackBarForCompleteUpdate()
}
state.installStatus() == INSTALLED -> {
appUpdateManager?.unregisterListener(this)
}
else -> {
Log.i(TAG, "InstallStateUpdatedListener: state: " + state.installStatus())
}
}
}
}
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (action != null && action == Intent.ACTION_SCREEN_OFF) {
if (PreferenceUtil.isLockScreen && isPlaying) {
val activity = Intent(context, LockScreenActivity::class.java)
activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
activity.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
ActivityCompat.startActivity(context, activity, null)
}
}
}
}
override fun createContentView(): View { override fun createContentView(): View {
return wrapSlidingMusicPanel(R.layout.activity_main_content) return wrapSlidingMusicPanel(R.layout.activity_main_content)
@ -122,29 +60,16 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
setTaskDescriptionColorAuto() setTaskDescriptionColorAuto()
hideStatusBar() hideStatusBar()
setBottomBarVisibility(View.VISIBLE) setBottomBarVisibility(View.VISIBLE)
addMusicServiceEventListener(libraryViewModel)
if (savedInstanceState == null) {
selectedFragment(PreferenceUtil.lastPage)
} else {
restoreCurrentFragment()
}
appLaunched(this) appLaunched(this)
setupToolbar() addMusicServiceEventListener(libraryViewModel)
checkUpdate()
updateTabs() updateTabs()
getBottomNavigationView().selectedItemId = PreferenceUtil.lastPage
getBottomNavigationView().setOnNavigationItemSelectedListener {
PreferenceUtil.lastPage = it.itemId
selectedFragment(it.itemId)
true
}
} }
override fun onSupportNavigateUp(): Boolean =
findNavController(R.id.fragment_container).navigateUp()
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
registerReceiver(broadcastReceiver, intentFilter)
PreferenceUtil.registerOnSharedPreferenceChangedListener(this) PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
if (intent.hasExtra(EXPAND_PANEL) && if (intent.hasExtra(EXPAND_PANEL) &&
intent.getBooleanExtra(EXPAND_PANEL, false) && intent.getBooleanExtra(EXPAND_PANEL, false) &&
@ -153,411 +78,13 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
expandPanel() expandPanel()
intent.removeExtra(EXPAND_PANEL) intent.removeExtra(EXPAND_PANEL)
} }
appUpdateManager?.appUpdateInfo
?.addOnSuccessListener { appUpdateInfo: AppUpdateInfo ->
if (appUpdateInfo.installStatus() == DOWNLOADED) {
popupSnackBarForCompleteUpdate()
}
try {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
appUpdateManager!!.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
APP_UPDATE_REQUEST_CODE
)
}
} catch (e: SendIntentException) {
e.printStackTrace()
}
}
} }
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
unregisterReceiver(broadcastReceiver)
PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this) PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this)
} }
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(this, toolbar)
return super.onPrepareOptionsMenu(menu)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
menu ?: return super.onCreateOptionsMenu(menu)
if (isPlaylistPage()) {
menu.add(0, R.id.action_new_playlist, 1, R.string.new_playlist_title)
.setIcon(R.drawable.ic_playlist_add)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}
if (isHomePage()) {
menu.add(0, R.id.action_mic, 1, getString(R.string.action_search))
.setIcon(R.drawable.ic_mic)
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}
if (isFolderPage()) {
menu.add(0, R.id.action_scan, 0, R.string.scan_media)
.setIcon(R.drawable.ic_scanner)
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
menu.add(0, R.id.action_go_to_start_directory, 1, R.string.action_go_to_start_directory)
.setIcon(R.drawable.ic_bookmark_music)
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}
val fragment: Fragment? = getCurrentFragment()
if (fragment != null && fragment is AbsRecyclerViewCustomGridSizeFragment<*, *>) {
val gridSizeItem: MenuItem = menu.findItem(R.id.action_grid_size)
if (RetroUtil.isLandscape()) {
gridSizeItem.setTitle(R.string.action_grid_size_land)
}
setUpGridSizeMenu(fragment, gridSizeItem.subMenu)
setupLayoutMenu(fragment, menu.findItem(R.id.action_layout_type).subMenu)
setUpSortOrderMenu(fragment, menu.findItem(R.id.action_sort_order).subMenu)
} else {
menu.removeItem(R.id.action_layout_type)
menu.removeItem(R.id.action_grid_size)
menu.removeItem(R.id.action_sort_order)
}
menu.add(0, R.id.action_settings, 6, getString(R.string.action_settings))
.setIcon(R.drawable.ic_settings)
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
menu.add(0, R.id.action_search, 0, getString(R.string.action_search))
.setIcon(R.drawable.ic_search)
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS)
ToolbarContentTintHelper.handleOnCreateOptionsMenu(
this,
toolbar,
menu,
getToolbarBackgroundColor(toolbar)
)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val fragment = getCurrentFragment()
if (fragment is AbsRecyclerViewCustomGridSizeFragment<*, *>) {
if (handleGridSizeMenuItem(fragment, item)) {
return true
}
if (handleLayoutResType(fragment, item)) {
return true
}
if (handleSortOrderMenuItem(fragment, item)) {
return true
}
}
when (item.itemId) {
R.id.action_search -> NavigationUtil.goToSearch(this)
R.id.action_new_playlist -> {
create().show(supportFragmentManager, "CREATE_PLAYLIST")
return true
}
R.id.action_mic -> {
val options = ActivityOptions.makeSceneTransitionAnimation(
this, toolbar,
getString(R.string.transition_toolbar)
)
NavigationUtil.goToSearch(this, true, options)
return true
}
R.id.action_settings -> {
NavigationUtil.goToSettings(this)
return true
}
}
return super.onOptionsItemSelected(item)
}
private fun handleSortOrderMenuItem(
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
item: MenuItem
): Boolean {
var sortOrder: String? = null
when (fragment) {
is AlbumsFragment -> {
when (item.itemId) {
R.id.action_album_sort_order_asc -> sortOrder = AlbumSortOrder.ALBUM_A_Z
R.id.action_album_sort_order_desc -> sortOrder = AlbumSortOrder.ALBUM_Z_A
R.id.action_album_sort_order_artist -> sortOrder = AlbumSortOrder.ALBUM_ARTIST
R.id.action_album_sort_order_year -> sortOrder = AlbumSortOrder.ALBUM_YEAR
}
}
is ArtistsFragment -> {
when (item.itemId) {
R.id.action_artist_sort_order_asc -> sortOrder = ArtistSortOrder.ARTIST_A_Z
R.id.action_artist_sort_order_desc -> sortOrder = ArtistSortOrder.ARTIST_Z_A
}
}
is SongsFragment -> {
when (item.itemId) {
R.id.action_song_sort_order_asc -> sortOrder = SongSortOrder.SONG_A_Z
R.id.action_song_sort_order_desc -> sortOrder = SongSortOrder.SONG_Z_A
R.id.action_song_sort_order_artist -> sortOrder = SongSortOrder.SONG_ARTIST
R.id.action_song_sort_order_album -> sortOrder = SongSortOrder.SONG_ALBUM
R.id.action_song_sort_order_year -> sortOrder = SongSortOrder.SONG_YEAR
R.id.action_song_sort_order_date -> sortOrder = SongSortOrder.SONG_DATE
R.id.action_song_sort_order_composer -> sortOrder = SongSortOrder.COMPOSER
R.id.action_song_sort_order_date_modified ->
sortOrder = SongSortOrder.SONG_DATE_MODIFIED
}
}
}
if (sortOrder != null) {
item.isChecked = true
fragment.setAndSaveSortOrder(sortOrder)
return true
}
return false
}
private fun handleLayoutResType(
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
item: MenuItem
): Boolean {
var layoutRes = -1
when (item.itemId) {
R.id.action_layout_normal -> layoutRes = R.layout.item_grid
R.id.action_layout_card -> layoutRes = R.layout.item_card
R.id.action_layout_colored_card -> layoutRes = R.layout.item_card_color
R.id.action_layout_circular -> layoutRes = R.layout.item_grid_circle
R.id.action_layout_image -> layoutRes = R.layout.image
R.id.action_layout_gradient_image -> layoutRes = R.layout.item_image_gradient
}
if (layoutRes != -1) {
item.isChecked = true
fragment.setAndSaveLayoutRes(layoutRes)
return true
}
return false
}
private fun handleGridSizeMenuItem(
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
item: MenuItem
): Boolean {
var gridSize = 0
when (item.itemId) {
R.id.action_grid_size_1 -> gridSize = 1
R.id.action_grid_size_2 -> gridSize = 2
R.id.action_grid_size_3 -> gridSize = 3
R.id.action_grid_size_4 -> gridSize = 4
R.id.action_grid_size_5 -> gridSize = 5
R.id.action_grid_size_6 -> gridSize = 6
R.id.action_grid_size_7 -> gridSize = 7
R.id.action_grid_size_8 -> gridSize = 8
}
if (gridSize > 0) {
item.isChecked = true
fragment.setAndSaveGridSize(gridSize)
return true
}
return false
}
private fun setUpGridSizeMenu(
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
gridSizeMenu: SubMenu
) {
when (fragment.getGridSize()) {
1 -> gridSizeMenu.findItem(R.id.action_grid_size_1).isChecked = true
2 -> gridSizeMenu.findItem(R.id.action_grid_size_2).isChecked = true
3 -> gridSizeMenu.findItem(R.id.action_grid_size_3).isChecked = true
4 -> gridSizeMenu.findItem(R.id.action_grid_size_4).isChecked = true
5 -> gridSizeMenu.findItem(R.id.action_grid_size_5).isChecked = true
6 -> gridSizeMenu.findItem(R.id.action_grid_size_6).isChecked = true
7 -> gridSizeMenu.findItem(R.id.action_grid_size_7).isChecked = true
8 -> gridSizeMenu.findItem(R.id.action_grid_size_8).isChecked = true
}
val maxGridSize = fragment.maxGridSize
if (maxGridSize < 8) {
gridSizeMenu.findItem(R.id.action_grid_size_8).isVisible = false
}
if (maxGridSize < 7) {
gridSizeMenu.findItem(R.id.action_grid_size_7).isVisible = false
}
if (maxGridSize < 6) {
gridSizeMenu.findItem(R.id.action_grid_size_6).isVisible = false
}
if (maxGridSize < 5) {
gridSizeMenu.findItem(R.id.action_grid_size_5).isVisible = false
}
if (maxGridSize < 4) {
gridSizeMenu.findItem(R.id.action_grid_size_4).isVisible = false
}
if (maxGridSize < 3) {
gridSizeMenu.findItem(R.id.action_grid_size_3).isVisible = false
}
}
private fun setupLayoutMenu(
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
subMenu: SubMenu
) {
when (fragment.itemLayoutRes()) {
R.layout.item_card ->
subMenu.findItem(R.id.action_layout_card).isChecked = true
R.layout.item_card_color ->
subMenu.findItem(R.id.action_layout_colored_card).isChecked = true
R.layout.item_grid_circle ->
subMenu.findItem(R.id.action_layout_circular).isChecked = true
R.layout.image ->
subMenu.findItem(R.id.action_layout_image).isChecked = true
R.layout.item_image_gradient ->
subMenu.findItem(R.id.action_layout_gradient_image).isChecked = true
R.layout.item_grid ->
subMenu.findItem(R.id.action_layout_normal).isChecked = true
else ->
subMenu.findItem(R.id.action_layout_normal).isChecked = true
}
}
private fun setUpSortOrderMenu(
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
sortOrderMenu: SubMenu
) {
val currentSortOrder = fragment.getSortOrder()
sortOrderMenu.clear()
when (fragment) {
is AlbumsFragment -> {
sortOrderMenu.add(
0,
R.id.action_album_sort_order_asc,
0,
R.string.sort_order_a_z
).isChecked = currentSortOrder == AlbumSortOrder.ALBUM_A_Z
sortOrderMenu.add(
0,
R.id.action_album_sort_order_desc,
1,
R.string.sort_order_z_a
).isChecked =
currentSortOrder == AlbumSortOrder.ALBUM_Z_A
sortOrderMenu.add(
0,
R.id.action_album_sort_order_artist,
2,
R.string.sort_order_artist
).isChecked =
currentSortOrder == AlbumSortOrder.ALBUM_ARTIST
sortOrderMenu.add(
0,
R.id.action_album_sort_order_year,
3,
R.string.sort_order_year
).isChecked =
currentSortOrder == AlbumSortOrder.ALBUM_YEAR
}
is ArtistsFragment -> {
sortOrderMenu.add(
0,
R.id.action_artist_sort_order_asc,
0,
R.string.sort_order_a_z
).isChecked =
currentSortOrder == ArtistSortOrder.ARTIST_A_Z
sortOrderMenu.add(
0,
R.id.action_artist_sort_order_desc,
1,
R.string.sort_order_z_a
).isChecked =
currentSortOrder == ArtistSortOrder.ARTIST_Z_A
}
is SongsFragment -> {
sortOrderMenu.add(
0,
R.id.action_song_sort_order_asc,
0,
R.string.sort_order_a_z
).isChecked =
currentSortOrder == SongSortOrder.SONG_A_Z
sortOrderMenu.add(
0,
R.id.action_song_sort_order_desc,
1,
R.string.sort_order_z_a
).isChecked =
currentSortOrder == SongSortOrder.SONG_Z_A
sortOrderMenu.add(
0,
R.id.action_song_sort_order_artist,
2,
R.string.sort_order_artist
).isChecked =
currentSortOrder == SongSortOrder.SONG_ARTIST
sortOrderMenu.add(
0,
R.id.action_song_sort_order_album,
3,
R.string.sort_order_album
).isChecked =
currentSortOrder == SongSortOrder.SONG_ALBUM
sortOrderMenu.add(
0,
R.id.action_song_sort_order_year,
4,
R.string.sort_order_year
).isChecked =
currentSortOrder == SongSortOrder.SONG_YEAR
sortOrderMenu.add(
0,
R.id.action_song_sort_order_date,
5,
R.string.sort_order_date
).isChecked =
currentSortOrder == SongSortOrder.SONG_DATE
sortOrderMenu.add(
0,
R.id.action_song_sort_order_date_modified,
6,
R.string.sort_order_date_modified
).isChecked = currentSortOrder == SongSortOrder.SONG_DATE_MODIFIED
sortOrderMenu.add(
0,
R.id.action_song_sort_order_composer,
7,
R.string.sort_order_composer
).isChecked = currentSortOrder == SongSortOrder.COMPOSER
}
}
sortOrderMenu.setGroupCheckable(0, true, true)
}
private fun getCurrentFragment(): Fragment? {
return supportFragmentManager.findFragmentById(R.id.fragment_container)
}
private fun isFolderPage(): Boolean {
return supportFragmentManager.findFragmentByTag(FoldersFragment.TAG) is FoldersFragment
}
private fun isHomePage(): Boolean {
return supportFragmentManager.findFragmentByTag(BannerHomeFragment.TAG) is BannerHomeFragment
}
private fun isPlaylistPage(): Boolean {
return supportFragmentManager.findFragmentByTag(PlaylistsFragment.TAG) is PlaylistsFragment
}
fun addOnAppBarOffsetChangedListener(
changedListener: AppBarLayout.OnOffsetChangedListener
) {
appBarLayout.addOnOffsetChangedListener(changedListener)
}
fun removeOnAppBarOffsetChangedListener(
changedListener: AppBarLayout.OnOffsetChangedListener
) {
appBarLayout.removeOnOffsetChangedListener(changedListener)
}
fun getTotalAppBarScrollingRange(): Int {
return appBarLayout.totalScrollRange
}
override fun requestPermissions() { override fun requestPermissions() {
if (!blockRequestPermissions) { if (!blockRequestPermissions) {
@ -572,115 +99,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
} }
} }
private fun setupToolbar() {
toolbar.setBackgroundColor(resolveColor(this, R.attr.colorSurface))
appBarLayout.setBackgroundColor(resolveColor(this, R.attr.colorSurface))
setSupportActionBar(toolbar)
}
private fun checkUpdate() {
appUpdateManager = AppUpdateManagerFactory.create(this)
appUpdateManager?.registerListener(listener)
val appUpdateInfoTask: Task<AppUpdateInfo>? = appUpdateManager?.appUpdateInfo
appUpdateInfoTask?.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {
try {
appUpdateManager?.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
APP_UPDATE_REQUEST_CODE
)
} catch (e: SendIntentException) {
e.printStackTrace()
}
}
}
}
private fun popupSnackBarForCompleteUpdate() {
val snackBar =
Snackbar.make(
findViewById(R.id.mainContent),
"New app is ready!",
Snackbar.LENGTH_INDEFINITE
)
snackBar.setAction(
"Install"
) {
appUpdateManager?.completeUpdate()
}
snackBar.setActionTextColor(accentColor(this))
snackBar.show()
}
private fun setCurrentFragment(
fragment: Fragment,
tag: String
) {
supportFragmentManager.commit {
setCustomAnimations(
R.anim.retro_fragment_open_enter,
R.anim.retro_fragment_open_exit,
R.anim.retro_fragment_fade_enter,
R.anim.retro_fragment_fade_exit
)
replace(R.id.fragment_container, fragment, tag)
}
currentFragment = fragment as MainActivityFragmentCallbacks
}
private fun selectedFragment(itemId: Int) {
when (itemId) {
R.id.action_album -> setCurrentFragment(
AlbumsFragment.newInstance(),
AlbumsFragment.TAG
)
R.id.action_artist -> setCurrentFragment(
ArtistsFragment.newInstance(),
ArtistsFragment.TAG
)
R.id.action_playlist -> setCurrentFragment(
PlaylistsFragment.newInstance(),
PlaylistsFragment.TAG
)
R.id.action_genre -> setCurrentFragment(
GenresFragment.newInstance(),
GenresFragment.TAG
)
R.id.action_playing_queue -> setCurrentFragment(
PlayingQueueFragment.newInstance(),
PlayingQueueFragment.TAG
)
R.id.action_song -> setCurrentFragment(
SongsFragment.newInstance(),
SongsFragment.TAG
)
R.id.action_folder -> setCurrentFragment(
FoldersFragment.newInstance(this),
FoldersFragment.TAG
)
R.id.action_home -> setCurrentFragment(
BannerHomeFragment.newInstance(),
BannerHomeFragment.TAG
)
else -> setCurrentFragment(
BannerHomeFragment.newInstance(),
BannerHomeFragment.TAG
)
}
}
private fun restoreCurrentFragment() {
val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (fragment != null) {
currentFragment = fragment as MainActivityFragmentCallbacks
}
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == GENERAL_THEME || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES if (key == GENERAL_THEME || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES
) { ) {
@ -762,11 +180,12 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
} }
override fun handleBackPress(): Boolean { override fun handleBackPress(): Boolean {
getBottomNavigationView().menu.getItem(0).isChecked = true
if (cab != null && cab!!.isActive) { if (cab != null && cab!!.isActive) {
cab?.finish() cab?.finish()
return true return true
} }
return super.handleBackPress() || currentFragment.handleBackPress() return super.handleBackPress()
} }
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab { override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
@ -787,4 +206,19 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
.start(callback) .start(callback)
return cab as MaterialCab return cab as MaterialCab
} }
override fun onColorSelection(dialog: ColorChooserDialog, selectedColor: Int) {
when (dialog.title) {
R.string.accent_color -> {
ThemeStore.editTheme(this).accentColor(selectedColor).commit()
if (VersionUtils.hasNougatMR())
DynamicShortcutManager(this).updateDynamicShortcuts()
}
}
recreate()
}
override fun onColorChooserDismissed(dialog: ColorChooserDialog) {
}
} }

View file

@ -1,104 +0,0 @@
package code.name.monkey.retromusic.activities
import android.os.Bundle
import android.view.MenuItem
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.extensions.applyToolbar
import com.afollestad.materialdialogs.color.ColorChooserDialog
import kotlinx.android.synthetic.main.activity_settings.*
class SettingsActivity : AbsBaseActivity(), ColorChooserDialog.ColorCallback {
private val fragmentManager = supportFragmentManager
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
setStatusbarColorAuto()
setNavigationbarColorAuto()
setLightNavigationBar(true)
setupToolbar()
}
private fun setupToolbar() {
setTitle(R.string.action_settings)
applyToolbar(toolbar)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.contentFrame) as NavHostFragment
val navController: NavController = navHostFragment.navController
navController.addOnDestinationChangedListener { _, _, _ ->
toolbar.title = navController.currentDestination?.label
}
//It removes the back button
//appBarConfiguration = AppBarConfiguration(navController.graph)
//setupActionBarWithNavController(navController, appBarConfiguration)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp() || super.onSupportNavigateUp()
}
fun setupFragment(fragment: Fragment, @StringRes titleName: Int) {
val fragmentTransaction = fragmentManager
.beginTransaction()
.setCustomAnimations(
R.anim.sliding_in_left,
R.anim.sliding_out_right,
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()
setTitle(titleName)
}
override fun onBackPressed() {
if (fragmentManager.backStackEntryCount == 0) {
super.onBackPressed()
} else {
setTitle(R.string.action_settings)
fragmentManager.popBackStack()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
onBackPressed()
return true
}
return super.onOptionsItemSelected(item)
}
companion object {
const val TAG: String = "SettingsActivity"
}
override fun onColorSelection(dialog: ColorChooserDialog, selectedColor: Int) {
when (dialog.title) {
R.string.accent_color -> {
ThemeStore.editTheme(this).accentColor(selectedColor).commit()
if (VersionUtils.hasNougatMR())
DynamicShortcutManager(this).updateDynamicShortcuts()
}
}
recreate()
}
override fun onColorChooserDismissed(dialog: ColorChooserDialog) {
}
}

View file

@ -1,399 +0,0 @@
package code.name.monkey.retromusic.activities.albums
import android.app.ActivityOptions
import android.content.Intent
import android.os.Bundle
import android.transition.Slide
import android.view.Menu
import android.view.MenuItem
import android.view.SubMenu
import android.view.View
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
import code.name.monkey.retromusic.activities.tageditor.AlbumTagEditorActivity
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.extensions.surfaceColor
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.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.model.LastFmAlbum
import code.name.monkey.retromusic.util.*
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.afollestad.materialcab.MaterialCab
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_album.*
import kotlinx.android.synthetic.main.activity_album_content.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
import android.util.Pair as UtilPair
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
cab?.let {
if (it.isActive) it.finish()
}
cab = MaterialCab(this, R.id.cab_stub)
.setMenu(menuRes)
.setCloseDrawableRes(R.drawable.ic_close)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(
ATHUtil.resolveColor(
this,
R.attr.colorSurface
)
)
)
.start(callback)
return cab as MaterialCab
}
private val detailsViewModel by viewModel<AlbumDetailsViewModel> {
parametersOf(extraNotNull<Int>(EXTRA_ALBUM_ID).value)
}
private lateinit var simpleSongAdapter: SimpleSongAdapter
private lateinit var album: Album
private var cab: MaterialCab? = null
private val savedSortOrder: String
get() = PreferenceUtil.albumDetailSongSortOrder
override fun createContentView(): View {
return wrapSlidingMusicPanel(R.layout.activity_album)
}
private fun windowEnterTransition() {
val slide = Slide()
slide.excludeTarget(R.id.appBarLayout, true)
slide.excludeTarget(R.id.status_bar, true)
slide.excludeTarget(android.R.id.statusBarBackground, true)
slide.excludeTarget(android.R.id.navigationBarBackground, true)
window.enterTransition = slide
}
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
setStatusbarColorAuto()
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
setLightNavigationBar(true)
setBottomBarVisibility(View.GONE)
window.sharedElementsUseOverlay = true
windowEnterTransition()
toolbar.setBackgroundColor(surfaceColor())
addMusicServiceEventListener(detailsViewModel)
ActivityCompat.postponeEnterTransition(this)
detailsViewModel.getAlbum().observe(this, androidx.lifecycle.Observer {
ActivityCompat.startPostponedEnterTransition(this@AlbumDetailsActivity)
showAlbum(it)
})
detailsViewModel.getArtist().observe(this, androidx.lifecycle.Observer {
loadArtistImage(it)
})
detailsViewModel.getMoreAlbums().observe(this, androidx.lifecycle.Observer {
moreAlbums(it)
})
detailsViewModel.getAlbumInfo().observe(this, androidx.lifecycle.Observer {
aboutAlbum(it)
})
setupRecyclerView()
artistImage.setOnClickListener {
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(
this,
UtilPair.create(
artistImage,
getString(R.string.transition_artist_image)
)
)
NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
}
playAction.apply {
setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
}
shuffleAction.apply {
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(album.songs!!, true) }
}
aboutAlbumText.setOnClickListener {
if (aboutAlbumText.maxLines == 4) {
aboutAlbumText.maxLines = Integer.MAX_VALUE
} else {
aboutAlbumText.maxLines = 4
}
}
}
private fun setupRecyclerView() {
simpleSongAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
recyclerView.apply {
layoutManager = LinearLayoutManager(this@AlbumDetailsActivity)
itemAnimator = DefaultItemAnimator()
isNestedScrollingEnabled = false
adapter = simpleSongAdapter
}
}
private fun showAlbum(album: Album) {
if (album.songs!!.isEmpty()) {
finish()
return
}
this.album = album
albumTitle.text = album.title
val songText =
resources.getQuantityString(
R.plurals.albumSongs,
album.songCount,
album.songCount
)
songTitle.text = songText
if (MusicUtil.getYearString(album.year) == "-") {
albumText.text = String.format(
"%s • %s",
album.artistName,
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
)
} else {
albumText.text = String.format(
"%s • %s • %s",
album.artistName,
MusicUtil.getYearString(album.year),
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
)
}
loadAlbumCover()
simpleSongAdapter.swapDataSet(album.songs)
detailsViewModel.loadArtist(album.artistId)
detailsViewModel.loadAlbumInfo(album)
}
private fun moreAlbums(albums: List<Album>) {
moreTitle.show()
moreRecyclerView.show()
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
val albumAdapter = HorizontalAlbumAdapter(this, albums, null)
moreRecyclerView.layoutManager = GridLayoutManager(
this,
1,
GridLayoutManager.HORIZONTAL,
false
)
moreRecyclerView.adapter = albumAdapter
}
private fun aboutAlbum(lastFmAlbum: LastFmAlbum) {
if (lastFmAlbum.album != null) {
if (lastFmAlbum.album.wiki != null) {
aboutAlbumText.show()
aboutAlbumTitle.show()
aboutAlbumTitle.text =
String.format(getString(R.string.about_album_label), lastFmAlbum.album.name)
aboutAlbumText.text = lastFmAlbum.album.wiki.content
}
if (lastFmAlbum.album.listeners.isNotEmpty()) {
listeners.show()
listenersLabel.show()
scrobbles.show()
scrobblesLabel.show()
listeners.text = RetroUtil.formatValue(lastFmAlbum.album.listeners.toFloat())
scrobbles.text = RetroUtil.formatValue(lastFmAlbum.album.playcount.toFloat())
}
}
}
private fun loadArtistImage(artist: Artist) {
ArtistGlideRequest.Builder.from(Glide.with(this), artist)
.generatePalette(this)
.build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(artistImage) {
override fun onColorReady(colors: MediaNotificationProcessor) {
}
})
}
private fun loadAlbumCover() {
AlbumGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong())
.checkIgnoreMediaStore(this)
.ignoreMediaStore(PreferenceUtil.isIgnoreMediaStoreArtwork)
.generatePalette(this)
.build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors)
}
})
}
private fun setColors(color: MediaNotificationProcessor) {
MaterialUtil.tintColor(
button = shuffleAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
MaterialUtil.tintColor(
button = playAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
setSupportActionBar(toolbar)
supportActionBar?.title = null
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_album_detail, menu)
val sortOrder = menu.findItem(R.id.action_sort_order)
setUpSortOrderMenu(sortOrder.subMenu)
ToolbarContentTintHelper.handleOnCreateOptionsMenu(
this,
toolbar,
menu,
getToolbarBackgroundColor(toolbar)
)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return handleSortOrderMenuItem(item)
}
private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
var sortOrder: String? = null
val songs = simpleSongAdapter.dataSet
when (item.itemId) {
R.id.action_play_next -> {
MusicPlayerRemote.playNext(songs)
return true
}
R.id.action_add_to_current_playing -> {
MusicPlayerRemote.enqueue(songs)
return true
}
R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
return true
}
R.id.action_delete_from_device -> {
DeleteSongsDialog.create(songs).show(supportFragmentManager, "DELETE_SONGS")
return true
}
android.R.id.home -> {
super.onBackPressed()
return true
}
R.id.action_tag_editor -> {
val intent = Intent(this, AlbumTagEditorActivity::class.java)
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.id)
val options = ActivityOptions.makeSceneTransitionAnimation(
this,
albumCoverContainer,
"${getString(R.string.transition_album_art)}_${album.id}"
)
startActivityForResult(
intent,
TAG_EDITOR_REQUEST, options.toBundle()
)
return true
}
/*Sort*/
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
}
if (sortOrder != null) {
item.isChecked = true
setSaveSortOrder(sortOrder)
}
return true
}
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 = true
AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration)
.isChecked = true
}
}
private fun setSaveSortOrder(sortOrder: String) {
PreferenceUtil.albumDetailSongSortOrder = sortOrder
when (sortOrder) {
AlbumSongSortOrder.SONG_TRACK_LIST -> album.songs?.sortWith(Comparator { o1, o2 ->
o1.trackNumber.compareTo(
o2.trackNumber
)
})
AlbumSongSortOrder.SONG_A_Z -> album.songs?.sortWith(Comparator { o1, o2 ->
o1.title.compareTo(
o2.title
)
})
AlbumSongSortOrder.SONG_Z_A -> album.songs?.sortWith(Comparator { o1, o2 ->
o2.title.compareTo(
o1.title
)
})
AlbumSongSortOrder.SONG_DURATION -> album.songs?.sortWith(Comparator { o1, o2 ->
o1.duration.compareTo(
o2.duration
)
})
}
album.songs?.let { simpleSongAdapter.swapDataSet(it) }
}
override fun onBackPressed() {
if (cab != null && cab!!.isActive) {
cab?.finish()
} else {
super.onBackPressed()
}
}
override fun onDestroy() {
super.onDestroy()
removeMusicServiceEventListener(detailsViewModel)
}
companion object {
const val EXTRA_ALBUM_ID = "extra_album_id"
private const val TAG_EDITOR_REQUEST = 2001
}
}

View file

@ -1,324 +0,0 @@
package code.name.monkey.retromusic.activities.artists
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.text.Spanned
import android.transition.Slide
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.text.HtmlCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.model.LastFmArtist
import code.name.monkey.retromusic.util.CustomArtistImageUtil
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroColorUtil
import code.name.monkey.retromusic.util.RetroUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.afollestad.materialcab.MaterialCab
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_artist_content.*
import kotlinx.android.synthetic.main.activity_artist_details.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
import kotlin.collections.ArrayList
class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
cab?.let {
if (it.isActive) it.finish()
}
cab = MaterialCab(this, R.id.cab_stub)
.setMenu(menuRes)
.setCloseDrawableRes(R.drawable.ic_close)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(
ATHUtil.resolveColor(
this,
R.attr.colorSurface
)
)
)
.start(callback)
return cab as MaterialCab
}
private var cab: MaterialCab? = null
private var biography: Spanned? = null
private lateinit var artist: Artist
private lateinit var songAdapter: SimpleSongAdapter
private lateinit var albumAdapter: HorizontalAlbumAdapter
private var forceDownload: Boolean = false
private val detailsViewModel: ArtistDetailsViewModel by viewModel {
parametersOf(extraNotNull<Int>(EXTRA_ARTIST_ID).value)
}
override fun createContentView(): View {
return wrapSlidingMusicPanel(R.layout.activity_artist_details)
}
private fun windowEnterTransition() {
val slide = Slide()
slide.excludeTarget(R.id.appBarLayout, true)
slide.excludeTarget(R.id.status_bar, true)
slide.excludeTarget(android.R.id.statusBarBackground, true)
slide.excludeTarget(android.R.id.navigationBarBackground, true)
window.enterTransition = slide
}
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
setStatusbarColorAuto()
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
setLightNavigationBar(true)
setBottomBarVisibility(View.GONE)
window.sharedElementsUseOverlay = true
windowEnterTransition()
toolbar.setBackgroundColor(surfaceColor())
addMusicServiceEventListener(detailsViewModel)
ActivityCompat.postponeEnterTransition(this)
detailsViewModel.getArtist().observe(this, androidx.lifecycle.Observer {
ActivityCompat.startPostponedEnterTransition(this@ArtistDetailActivity)
artist(it)
})
detailsViewModel.getArtistInfo().observe(this, androidx.lifecycle.Observer {
artistInfo(it)
})
setupRecyclerView()
playAction.apply {
setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
}
shuffleAction.apply {
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) }
}
biographyText.setOnClickListener {
if (biographyText.maxLines == 4) {
biographyText.maxLines = Integer.MAX_VALUE
} else {
biographyText.maxLines = 4
}
}
}
private fun setupRecyclerView() {
albumAdapter = HorizontalAlbumAdapter(this, ArrayList(), null)
albumRecyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = GridLayoutManager(this.context, 1, GridLayoutManager.HORIZONTAL, false)
adapter = albumAdapter
}
songAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
recyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = LinearLayoutManager(this.context)
adapter = songAdapter
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
data?.data?.let {
CustomArtistImageUtil.getInstance(this).setCustomArtistImage(artist, it)
}
}
else -> if (resultCode == Activity.RESULT_OK) {
//reload()
}
}
}
fun artist(artist: Artist) {
if (artist.songs.isEmpty()) {
finish()
}
this.artist = artist
loadArtistImage(artist)
if (RetroUtil.isAllowedToDownloadMetadata(this)) {
loadBiography(artist.name)
}
artistTitle.text = artist.name
text.text = String.format(
"%s • %s",
MusicUtil.getArtistInfoString(this, artist),
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs))
)
val songText =
resources.getQuantityString(
R.plurals.albumSongs,
artist.songCount,
artist.songCount
)
val albumText =
resources.getQuantityString(
R.plurals.albums,
artist.songCount,
artist.songCount
)
songTitle.text = songText
albumTitle.text = albumText
songAdapter.swapDataSet(artist.songs)
artist.albums?.let { albumAdapter.swapDataSet(it) }
}
private fun loadBiography(
name: String,
lang: String? = Locale.getDefault().language
) {
biography = null
this.lang = lang
detailsViewModel.loadBiography(name, lang, null)
}
private fun artistInfo(lastFmArtist: LastFmArtist?) {
if (lastFmArtist != null && lastFmArtist.artist != null) {
val bioContent = lastFmArtist.artist.bio.content
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
biographyText.visibility = View.VISIBLE
biographyTitle.visibility = View.VISIBLE
biography = HtmlCompat.fromHtml(bioContent, HtmlCompat.FROM_HTML_MODE_LEGACY)
biographyText.text = biography
if (lastFmArtist.artist.stats.listeners.isNotEmpty()) {
listeners.show()
listenersLabel.show()
scrobbles.show()
scrobblesLabel.show()
listeners.text =
RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat())
scrobbles.text =
RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat())
}
}
}
// If the "lang" parameter is set and no biography is given, retry with default language
if (biography == null && lang != null) {
loadBiography(artist.name, null)
}
}
private var lang: String? = null
private fun loadArtistImage(artist: Artist) {
ArtistGlideRequest.Builder.from(Glide.with(this), artist)
.generatePalette(this).build()
.dontAnimate().into(object : RetroMusicColoredTarget(image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors)
}
})
}
private fun setColors(color: MediaNotificationProcessor) {
MaterialUtil.tintColor(
button = shuffleAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
MaterialUtil.tintColor(
button = playAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
setSupportActionBar(toolbar)
supportActionBar?.title = null
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return handleSortOrderMenuItem(item)
}
private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
val songs = artist.songs
when (item.itemId) {
android.R.id.home -> {
super.onBackPressed()
return true
}
R.id.action_play_next -> {
MusicPlayerRemote.playNext(songs)
return true
}
R.id.action_add_to_current_playing -> {
MusicPlayerRemote.enqueue(songs)
return true
}
R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
return true
}
R.id.action_set_artist_image -> {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
startActivityForResult(
Intent.createChooser(intent, getString(R.string.pick_from_local_storage)),
REQUEST_CODE_SELECT_IMAGE
)
return true
}
R.id.action_reset_artist_image -> {
Toast.makeText(
this@ArtistDetailActivity,
resources.getString(R.string.updating),
Toast.LENGTH_SHORT
)
.show()
CustomArtistImageUtil.getInstance(this@ArtistDetailActivity)
.resetCustomArtistImage(artist)
forceDownload = true
return true
}
}
return true
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_artist_detail, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onBackPressed() {
if (cab != null && cab!!.isActive) {
cab?.finish()
} else {
super.onBackPressed()
}
}
override fun onDestroy() {
super.onDestroy()
removeMusicServiceEventListener(detailsViewModel)
}
companion object {
const val EXTRA_ARTIST_ID = "extra_artist_id"
const val REQUEST_CODE_SELECT_IMAGE = 9003
}
}

View file

@ -12,15 +12,13 @@ import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.RetroBottomSheetBehavior import code.name.monkey.retromusic.RetroBottomSheetBehavior
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.MiniPlayerFragment import code.name.monkey.retromusic.fragments.MiniPlayerFragment
import code.name.monkey.retromusic.fragments.NowPlayingScreen import code.name.monkey.retromusic.fragments.NowPlayingScreen
import code.name.monkey.retromusic.fragments.NowPlayingScreen.* import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.CategoryInfo import code.name.monkey.retromusic.model.CategoryInfo
import code.name.monkey.retromusic.util.DensityUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.views.BottomNavigationBarTinted import code.name.monkey.retromusic.views.BottomNavigationBarTinted
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
@ -178,19 +176,18 @@ abstract class AbsSlidingMusicPanelActivity() : AbsMusicServiceActivity() {
} }
private fun hideBottomBar(hide: Boolean) { private fun hideBottomBar(hide: Boolean) {
val heightOfBar = resources.getDimensionPixelSize(R.dimen.mini_player_height) val heightOfBar = dimToPixel(R.dimen.mini_player_height)
val heightOfBarWithTabs = val heightOfBarWithTabs = dimToPixel(R.dimen.mini_player_height_expanded)
resources.getDimensionPixelSize(R.dimen.mini_player_height_expanded)
if (hide) { if (hide) {
behavior.isHideable = true behavior.isHideable = true
behavior.peekHeight = 0 behavior.peekHeight = 0
bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat() bottomNavigationView.elevation = dipToPix(10f)
collapsePanel() collapsePanel()
} else { } else {
if (MusicPlayerRemote.playingQueue.isNotEmpty()) { if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
slidingPanel.elevation = DensityUtil.dip2px(this, 10f).toFloat() slidingPanel.elevation = dipToPix(10f)
bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat() bottomNavigationView.elevation = dipToPix(10f)
behavior.isHideable = false behavior.isHideable = false
behavior.peekHeight = behavior.peekHeight =
if (bottomNavigationView.visibility == View.VISIBLE) { if (bottomNavigationView.visibility == View.VISIBLE) {
@ -204,8 +201,7 @@ abstract class AbsSlidingMusicPanelActivity() : AbsMusicServiceActivity() {
private fun chooseFragmentForTheme() { private fun chooseFragmentForTheme() {
cps = PreferenceUtil.nowPlayingScreen cps = PreferenceUtil.nowPlayingScreen
miniPlayerFragment = miniPlayerFragment = whichFragment<MiniPlayerFragment>(R.id.miniPlayerFragment)
supportFragmentManager.findFragmentById(R.id.miniPlayerFragment) as MiniPlayerFragment
miniPlayerFragment?.view?.setOnClickListener { expandPanel() } miniPlayerFragment?.view?.setOnClickListener { expandPanel() }
} }
@ -232,7 +228,6 @@ abstract class AbsSlidingMusicPanelActivity() : AbsMusicServiceActivity() {
} }
open fun handleBackPress(): Boolean { open fun handleBackPress(): Boolean {
if (panelState == BottomSheetBehavior.STATE_EXPANDED) { if (panelState == BottomSheetBehavior.STATE_EXPANDED) {
collapsePanel() collapsePanel()
return true return true
@ -305,6 +300,11 @@ abstract class AbsSlidingMusicPanelActivity() : AbsMusicServiceActivity() {
} }
} }
fun hideBottomNavigation() {
behavior.isHideable = true
behavior.state == BottomSheetBehavior.STATE_HIDDEN
}
fun updateTabs() { fun updateTabs() {
bottomNavigationView.menu.clear() bottomNavigationView.menu.clear()
val currentTabs: List<CategoryInfo> = PreferenceUtil.libraryCategory val currentTabs: List<CategoryInfo> = PreferenceUtil.libraryCategory

View file

@ -1,143 +0,0 @@
package code.name.monkey.retromusic.activities.genre
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
import code.name.monkey.retromusic.adapter.song.ShuffleButtonSongAdapter
import code.name.monkey.retromusic.extensions.applyToolbar
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.helper.menu.GenreMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Song
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.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
/**
* @author Hemanth S (h4h13).
*/
class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
private val detailsViewModel: GenreDetailsViewModel by viewModel {
parametersOf(extraNotNull<Genre>(EXTRA_GENRE_ID).value)
}
private lateinit var genre: Genre
private lateinit var songAdapter: ShuffleButtonSongAdapter
private var cab: MaterialCab? = null
private fun getEmojiByUnicode(unicode: Int): String {
return String(Character.toChars(unicode))
}
private fun checkIsEmpty() {
checkForPadding()
emptyEmoji.text = getEmojiByUnicode(0x1F631)
empty?.visibility = if (songAdapter.itemCount == 0) View.VISIBLE else View.GONE
}
private fun checkForPadding() {
val height = DensityUtil.dip2px(this, 52f)
recyclerView.setPadding(0, 0, 0, (height))
}
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
setStatusbarColorAuto()
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
setLightNavigationBar(true)
setBottomBarVisibility(View.GONE)
applyToolbar(toolbar)
setupRecyclerView()
detailsViewModel.getSongs().observe(this, androidx.lifecycle.Observer {
songs(it)
})
detailsViewModel.getGenre().observe(this, androidx.lifecycle.Observer {
genre = it
supportActionBar?.title = it.name
})
addMusicServiceEventListener(detailsViewModel)
}
override fun createContentView(): View {
return wrapSlidingMusicPanel(R.layout.activity_playlist_detail)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_genre_detail, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
onBackPressed()
}
return GenreMenuHelper.handleMenuClick(this, genre, item)
}
private fun setupRecyclerView() {
songAdapter = ShuffleButtonSongAdapter(this, ArrayList(), R.layout.item_list, this)
recyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = LinearLayoutManager(this@GenreDetailsActivity)
adapter = songAdapter
}
songAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
super.onChanged()
checkIsEmpty()
}
})
}
fun songs(songs: List<Song>) {
songAdapter.swapDataSet(songs)
}
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)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(
ATHUtil.resolveColor(
this,
R.attr.colorSurface
)
)
).start(callback)
return cab!!
}
override fun onBackPressed() {
if (cab != null && cab!!.isActive) cab!!.finish()
else {
recyclerView!!.stopScroll()
super.onBackPressed()
}
}
companion object {
const val EXTRA_GENRE_ID = "extra_genre_id"
}
}

View file

@ -35,7 +35,7 @@ import kotlin.collections.ArrayList
class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher { class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher {
private val viewModel: SearchViewModel by inject() private val viewModel: SearchViewModel by inject()
private var searchAdapter: SearchAdapter? = null private lateinit var searchAdapter: SearchAdapter
private var query: String? = null private var query: String? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -87,10 +87,10 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
private fun setupRecyclerView() { private fun setupRecyclerView() {
searchAdapter = SearchAdapter(this, emptyList()) searchAdapter = SearchAdapter(this, emptyList())
searchAdapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { searchAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
empty.visibility = if (searchAdapter!!.itemCount < 1) View.VISIBLE else View.GONE empty.visibility = if (searchAdapter.itemCount < 1) View.VISIBLE else View.GONE
} }
}) })
recyclerView.apply { recyclerView.apply {
@ -152,15 +152,11 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
} }
} }
private fun showEmptyView() {
searchAdapter?.swapDataSet(ArrayList())
}
private fun showData(data: MutableList<Any>) { private fun showData(data: MutableList<Any>) {
if (data.isNotEmpty()) { if (data.isNotEmpty()) {
searchAdapter?.swapDataSet(data) searchAdapter.swapDataSet(data)
} else { } else {
showEmptyView() searchAdapter.swapDataSet(ArrayList())
} }
} }
@ -215,7 +211,7 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
const val EXTRA_SHOW_MIC = "extra_show_mic" const val EXTRA_SHOW_MIC = "extra_show_mic"
const val QUERY: String = "query" const val QUERY: String = "query"
private const val REQ_CODE_SPEECH_INPUT = 9002 const val REQ_CODE_SPEECH_INPUT = 9002
} }
} }

View file

@ -0,0 +1,134 @@
package code.name.monkey.retromusic.activities.search
import android.content.ActivityNotFoundException
import android.content.Intent
import android.os.Bundle
import android.speech.RecognizerIntent
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat.getSystemService
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.SearchAdapter
import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.fragments.MainActivityFragment
import kotlinx.android.synthetic.main.fragment_search.*
import org.koin.android.ext.android.inject
import java.util.*
import kotlin.collections.ArrayList
class SearchFragment : MainActivityFragment(R.layout.fragment_search), TextWatcher {
private val viewModel: SearchViewModel by inject()
private lateinit var searchAdapter: SearchAdapter
private var query: String? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
setupSearchView()
mainActivity.setSupportActionBar(toolbar)
mainActivity.setBottomBarVisibility(View.GONE)
voiceSearch.setOnClickListener { startMicSearch() }
clearText.setOnClickListener { searchView.clearText() }
keyboardPopup.setOnClickListener {
val inputManager =
getSystemService<InputMethodManager>(
requireContext(),
InputMethodManager::class.java
)
inputManager?.showSoftInput(searchView, InputMethodManager.SHOW_IMPLICIT)
}
keyboardPopup.accentColor()
if (savedInstanceState != null) {
query = savedInstanceState.getString(SearchActivity.QUERY)
}
viewModel.getSearchResult().observe(viewLifecycleOwner, Observer {
showData(it)
})
}
private fun showData(data: MutableList<Any>) {
if (data.isNotEmpty()) {
searchAdapter.swapDataSet(data)
} else {
searchAdapter.swapDataSet(ArrayList())
}
}
private fun setupRecyclerView() {
searchAdapter = SearchAdapter(requireActivity() as AppCompatActivity, emptyList())
searchAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
super.onChanged()
empty.visibility = if (searchAdapter.itemCount < 1) View.VISIBLE else View.GONE
}
})
recyclerView.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = searchAdapter
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (dy > 0) {
keyboardPopup.shrink()
} else if (dy < 0) {
keyboardPopup.extend()
}
}
})
}
}
private fun setupSearchView() {
searchView.addTextChangedListener(this)
}
override fun afterTextChanged(newText: Editable?) {
search(newText.toString())
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
private fun search(query: String) {
this.query = query
TransitionManager.beginDelayedTransition(appBarLayout)
voiceSearch.visibility = if (query.isNotEmpty()) View.GONE else View.VISIBLE
clearText.visibility = if (query.isNotEmpty()) View.VISIBLE else View.GONE
viewModel.search(query)
}
private fun startMicSearch() {
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
intent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
)
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
try {
startActivityForResult(
intent,
SearchActivity.REQ_CODE_SPEECH_INPUT
)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
showToast(getString(R.string.speech_not_supported))
}
}
}

View file

@ -1,14 +1,16 @@
package code.name.monkey.retromusic.adapter package code.name.monkey.retromusic.adapter
import android.app.Activity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.EXTRA_GENRE
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.util.NavigationUtil
import java.util.* import java.util.*
/** /**
@ -16,7 +18,7 @@ import java.util.*
*/ */
class GenreAdapter( class GenreAdapter(
private val activity: Activity, private val activity: FragmentActivity,
var dataSet: List<Genre>, var dataSet: List<Genre>,
private val mItemLayoutRes: Int private val mItemLayoutRes: Int
) : RecyclerView.Adapter<GenreAdapter.ViewHolder>() { ) : RecyclerView.Adapter<GenreAdapter.ViewHolder>() {
@ -48,9 +50,10 @@ class GenreAdapter(
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) { inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
override fun onClick(v: View?) { override fun onClick(v: View?) {
super.onClick(v) activity.findNavController(R.id.fragment_container).navigate(
val genre = dataSet[layoutPosition] R.id.genreDetailsFragment,
NavigationUtil.goToGenre(activity, genre) bundleOf(EXTRA_GENRE to dataSet[layoutPosition])
)
} }
} }
} }

View file

@ -1,6 +1,5 @@
package code.name.monkey.retromusic.adapter package code.name.monkey.retromusic.adapter
import android.util.DisplayMetrics
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -8,18 +7,24 @@ import android.widget.TextView
import androidx.annotation.IntDef import androidx.annotation.IntDef
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.os.bundleOf
import androidx.navigation.findNavController
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.HORIZONTAL import androidx.recyclerview.widget.RecyclerView.HORIZONTAL
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.PeekingLinearLayoutManager import code.name.monkey.retromusic.PeekingLinearLayoutManager
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.AlbumAdapter import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
import code.name.monkey.retromusic.fragments.artists.ArtistClickListener
import code.name.monkey.retromusic.glide.SongGlideRequest import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
@ -29,8 +34,7 @@ import com.bumptech.glide.Glide
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
class HomeAdapter( class HomeAdapter(
private val activity: AppCompatActivity, private val activity: AppCompatActivity
private val displayMetrics: DisplayMetrics
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var list = listOf<Home>() private var list = listOf<Home>()
@ -143,21 +147,28 @@ class HomeAdapter(
const val GENRES = 6 const val GENRES = 6
} }
private inner class AlbumViewHolder(view: View) : AbsHomeViewItem(view) { private inner class AlbumViewHolder(view: View) : AbsHomeViewItem(view), AlbumClickListener {
fun bindView(list: List<Album>, titleRes: Int) { fun bindView(list: List<Album>, titleRes: Int) {
if (list.isNotEmpty()) { if (list.isNotEmpty()) {
val albumAdapter = AlbumAdapter(activity, list, R.layout.pager_item, null, this)
recyclerView.apply { recyclerView.apply {
show() show()
adapter = AlbumAdapter(activity, list, R.layout.pager_item, null) adapter = albumAdapter
layoutManager = layoutManager = PeekingLinearLayoutManager(activity, HORIZONTAL, false)
PeekingLinearLayoutManager(activity, HORIZONTAL, false)
} }
title.text = activity.getString(titleRes) title.text = activity.getString(titleRes)
} }
} }
override fun onAlbumClick(albumId: Int) {
activity.findNavController(R.id.fragment_container).navigate(
R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to albumId)
)
}
} }
inner class ArtistViewHolder(view: View) : AbsHomeViewItem(view) { private inner class ArtistViewHolder(view: View) : AbsHomeViewItem(view), ArtistClickListener {
fun bindView(list: List<Artist>, titleRes: Int) { fun bindView(list: List<Artist>, titleRes: Int) {
if (list.isNotEmpty()) { if (list.isNotEmpty()) {
val manager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false) val manager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
@ -165,7 +176,8 @@ class HomeAdapter(
activity, activity,
list, list,
PreferenceUtil.homeGridStyle, PreferenceUtil.homeGridStyle,
null null,
this
) )
recyclerView.apply { recyclerView.apply {
show() show()
@ -175,6 +187,13 @@ class HomeAdapter(
title.text = activity.getString(titleRes) title.text = activity.getString(titleRes)
} }
} }
override fun onArtist(artistId: Int) {
activity.findNavController(R.id.fragment_container).navigate(
R.id.artistDetailsFragment,
bundleOf(EXTRA_ARTIST_ID to artistId)
)
}
} }
private inner class SuggestionsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private inner class SuggestionsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

View file

@ -1,13 +1,14 @@
package code.name.monkey.retromusic.adapter package code.name.monkey.retromusic.adapter
import android.app.ActivityOptions
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.glide.AlbumGlideRequest import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
@ -17,13 +18,11 @@ import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import android.util.Pair as UtilPair
class SearchAdapter( class SearchAdapter(
private val activity: AppCompatActivity, private val activity: FragmentActivity,
private var dataSet: List<Any>? private var dataSet: List<Any>
) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() { ) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() {
fun swapDataSet(dataSet: MutableList<Any>) { fun swapDataSet(dataSet: MutableList<Any>) {
@ -32,11 +31,11 @@ class SearchAdapter(
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
if (dataSet!![position] is Album) return ALBUM if (dataSet[position] is Album) return ALBUM
if (dataSet!![position] is Artist) return ARTIST if (dataSet[position] is Artist) return ARTIST
if (dataSet!![position] is Genre) return GENRE if (dataSet[position] is Genre) return GENRE
if (dataSet!![position] is Playlist) return PLAYLIST if (dataSet[position] is Playlist) return PLAYLIST
return if (dataSet!![position] is Song) SONG else HEADER return if (dataSet[position] is Song) SONG else HEADER
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -57,35 +56,35 @@ class SearchAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
when (getItemViewType(position)) { when (getItemViewType(position)) {
ALBUM -> { ALBUM -> {
val album = dataSet?.get(position) as Album val album = dataSet.get(position) as Album
holder.title?.text = album.title holder.title?.text = album.title
holder.text?.text = album.artistName holder.text?.text = album.artistName
AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity).build().into(holder.image) .checkIgnoreMediaStore(activity).build().into(holder.image)
} }
ARTIST -> { ARTIST -> {
val artist = dataSet?.get(position) as Artist val artist = dataSet.get(position) as Artist
holder.title?.text = artist.name holder.title?.text = artist.name
holder.text?.text = MusicUtil.getArtistInfoString(activity, artist) holder.text?.text = MusicUtil.getArtistInfoString(activity, artist)
ArtistGlideRequest.Builder.from(Glide.with(activity), artist).build() ArtistGlideRequest.Builder.from(Glide.with(activity), artist).build()
.into(holder.image) .into(holder.image)
} }
SONG -> { SONG -> {
val song = dataSet?.get(position) as Song val song = dataSet.get(position) as Song
holder.title?.text = song.title holder.title?.text = song.title
holder.text?.text = song.albumName holder.text?.text = song.albumName
} }
GENRE -> { GENRE -> {
val genre = dataSet?.get(position) as Genre val genre = dataSet.get(position) as Genre
holder.title?.text = genre.name holder.title?.text = genre.name
} }
PLAYLIST -> { PLAYLIST -> {
val playlist = dataSet?.get(position) as Playlist val playlist = dataSet.get(position) as Playlist
holder.title?.text = playlist.name holder.title?.text = playlist.name
holder.text?.text = MusicUtil.getPlaylistInfoString(activity, getSongs(playlist)) holder.text?.text = MusicUtil.getPlaylistInfoString(activity, getSongs(playlist))
} }
else -> { else -> {
holder.title?.text = dataSet?.get(position).toString() holder.title?.text = dataSet.get(position).toString()
holder.title?.setTextColor(ThemeStore.accentColor(activity)) holder.title?.setTextColor(ThemeStore.accentColor(activity))
} }
} }
@ -102,7 +101,7 @@ class SearchAdapter(
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
return dataSet!!.size return dataSet.size
} }
inner class ViewHolder(itemView: View, itemViewType: Int) : MediaEntryViewHolder(itemView) { inner class ViewHolder(itemView: View, itemViewType: Int) : MediaEntryViewHolder(itemView) {
@ -113,7 +112,7 @@ class SearchAdapter(
menu?.visibility = View.VISIBLE menu?.visibility = View.VISIBLE
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) { menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song override val song: Song
get() = dataSet!![layoutPosition] as Song get() = dataSet[layoutPosition] as Song
}) })
} else { } else {
menu?.visibility = View.GONE menu?.visibility = View.GONE
@ -130,27 +129,31 @@ class SearchAdapter(
} }
override fun onClick(v: View?) { override fun onClick(v: View?) {
val item = dataSet!![layoutPosition] val item = dataSet[layoutPosition]
when (itemViewType) { when (itemViewType) {
ALBUM -> { ALBUM -> {
val options = ActivityOptions.makeSceneTransitionAnimation( activity.findNavController(R.id.fragment_container).navigate(
activity, R.id.albumDetailsFragment,
UtilPair.create(image, activity.getString(R.string.transition_album_art)) bundleOf(EXTRA_ALBUM_ID to (item as Album).id)
) )
NavigationUtil.goToAlbumOptions(activity, (item as Album).id, options)
} }
ARTIST -> { ARTIST -> {
val options = ActivityOptions.makeSceneTransitionAnimation( activity.findNavController(R.id.fragment_container).navigate(
activity, R.id.artistDetailsFragment,
UtilPair.create(image, activity.getString(R.string.transition_artist_image)) bundleOf(EXTRA_ARTIST_ID to (item as Artist).id)
) )
NavigationUtil.goToArtistOptions(activity, (item as Artist).id, options)
} }
GENRE -> { GENRE -> {
NavigationUtil.goToGenre(activity, item as Genre) activity.findNavController(R.id.fragment_container).navigate(
R.id.genreDetailsFragment,
bundleOf(EXTRA_GENRE to (item as Genre))
)
} }
PLAYLIST -> { PLAYLIST -> {
NavigationUtil.goToPlaylistNew(activity, item as Playlist) activity.findNavController(R.id.fragment_container).navigate(
R.id.artistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to (item as Playlist))
)
} }
SONG -> { SONG -> {
val playList = ArrayList<Song>() val playList = ArrayList<Song>()

View file

@ -7,10 +7,11 @@ import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
import code.name.monkey.retromusic.glide.AlbumGlideRequest import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
@ -20,17 +21,17 @@ import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil 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.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import me.zhanghai.android.fastscroll.PopupTextProvider import me.zhanghai.android.fastscroll.PopupTextProvider
open class AlbumAdapter( open class AlbumAdapter(
protected val activity: AppCompatActivity, protected val activity: FragmentActivity,
var dataSet: List<Album>, var dataSet: List<Album>,
protected var itemLayoutRes: Int, protected var itemLayoutRes: Int,
cabHolder: CabHolder? cabHolder: CabHolder?,
private val albumClickListener: AlbumClickListener?
) : AbsMultiSelectAdapter<AlbumAdapter.ViewHolder, Album>( ) : AbsMultiSelectAdapter<AlbumAdapter.ViewHolder, Album>(
activity, activity,
cabHolder, cabHolder,
@ -177,11 +178,12 @@ open class AlbumAdapter(
imageContainerCard ?: image, imageContainerCard ?: image,
activity.getString(R.string.transition_album_art) activity.getString(R.string.transition_album_art)
) )
NavigationUtil.goToAlbumOptions( albumClickListener?.onAlbumClick(dataSet[layoutPosition].id)
/*NavigationUtil.goToAlbumOptions(
activity, activity,
dataSet[layoutPosition].id, dataSet[layoutPosition].id,
activityOptions activityOptions
) )*/
} }
} }

View file

@ -1,10 +1,10 @@
package code.name.monkey.retromusic.adapter.album package code.name.monkey.retromusic.adapter.album
import android.graphics.drawable.Drawable
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
import code.name.monkey.retromusic.glide.AlbumGlideRequest import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.HorizontalAdapterHelper import code.name.monkey.retromusic.helper.HorizontalAdapterHelper
@ -15,11 +15,12 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
class HorizontalAlbumAdapter( class HorizontalAlbumAdapter(
activity: AppCompatActivity, activity: FragmentActivity,
dataSet: List<Album>, dataSet: List<Album>,
cabHolder: CabHolder? cabHolder: CabHolder?,
albumClickListener: AlbumClickListener
) : AlbumAdapter( ) : AlbumAdapter(
activity, dataSet, HorizontalAdapterHelper.LAYOUT_RES, cabHolder activity, dataSet, HorizontalAdapterHelper.LAYOUT_RES, cabHolder, albumClickListener
) { ) {
override fun createViewHolder(view: View, viewType: Int): ViewHolder { override fun createViewHolder(view: View, viewType: Int): ViewHolder {
@ -40,11 +41,6 @@ class HorizontalAlbumAdapter(
.generatePalette(activity) .generatePalette(activity)
.build() .build()
.into(object : RetroMusicColoredTarget(holder.image!!) { .into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onLoadCleared(placeholder: Drawable?) {
super.onLoadCleared(placeholder)
//setColors(albumArtistFooterColor, holder)
}
override fun onColorReady(colors: MediaNotificationProcessor) { override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors, holder) setColors(colors, holder)
} }

View file

@ -7,11 +7,12 @@ import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.fragments.artists.ArtistClickListener
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
@ -19,17 +20,17 @@ import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import me.zhanghai.android.fastscroll.PopupTextProvider import me.zhanghai.android.fastscroll.PopupTextProvider
import java.util.* import java.util.*
class ArtistAdapter( class ArtistAdapter(
val activity: AppCompatActivity, val activity: FragmentActivity,
var dataSet: List<Artist>, var dataSet: List<Artist>,
var itemLayoutRes: Int, var itemLayoutRes: Int,
cabHolder: CabHolder? cabHolder: CabHolder?,
private val artistClickListener: ArtistClickListener
) : AbsMultiSelectAdapter<ArtistAdapter.ViewHolder, Artist>( ) : AbsMultiSelectAdapter<ArtistAdapter.ViewHolder, Artist>(
activity, cabHolder, R.menu.menu_media_selection activity, cabHolder, R.menu.menu_media_selection
), PopupTextProvider { ), PopupTextProvider {
@ -144,9 +145,10 @@ class ArtistAdapter(
imageContainerCard ?: image, imageContainerCard ?: image,
activity.getString(R.string.transition_artist_image) activity.getString(R.string.transition_artist_image)
) )
NavigationUtil.goToArtistOptions( artistClickListener.onArtist(dataSet[layoutPosition].id)
/*NavigationUtil.goToArtistOptions(
activity, dataSet[layoutPosition].id, activityOptions activity, dataSet[layoutPosition].id, activityOptions
) )*/
} }
} }

View file

@ -9,11 +9,14 @@ import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.EXTRA_PLAYLIST
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
@ -29,12 +32,11 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
import code.name.monkey.retromusic.util.AutoGeneratedPlaylistBitmap import code.name.monkey.retromusic.util.AutoGeneratedPlaylistBitmap
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.RetroColorUtil import code.name.monkey.retromusic.util.RetroColorUtil
import java.util.* import java.util.*
class PlaylistAdapter( class PlaylistAdapter(
private val activity: AppCompatActivity, private val activity: FragmentActivity,
var dataSet: List<Playlist>, var dataSet: List<Playlist>,
private var itemLayoutRes: Int, private var itemLayoutRes: Int,
cabHolder: CabHolder? cabHolder: CabHolder?
@ -165,9 +167,7 @@ class PlaylistAdapter(
val popupMenu = PopupMenu(activity, view) val popupMenu = PopupMenu(activity, view)
popupMenu.inflate(R.menu.menu_item_playlist) popupMenu.inflate(R.menu.menu_item_playlist)
popupMenu.setOnMenuItemClickListener { item -> popupMenu.setOnMenuItemClickListener { item ->
PlaylistMenuHelper.handleMenuClick( PlaylistMenuHelper.handleMenuClick(activity, dataSet[layoutPosition], item)
activity, dataSet[layoutPosition], item
)
} }
popupMenu.show() popupMenu.show()
} }
@ -182,8 +182,10 @@ class PlaylistAdapter(
if (isInQuickSelectMode) { if (isInQuickSelectMode) {
toggleChecked(layoutPosition) toggleChecked(layoutPosition)
} else { } else {
val playlist = dataSet[layoutPosition] activity.findNavController(R.id.fragment_container).navigate(
NavigationUtil.goToPlaylistNew(activity, playlist) R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to dataSet[layoutPosition])
)
} }
} }

View file

@ -2,7 +2,7 @@ package code.name.monkey.retromusic.adapter.song
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.R.menu import code.name.monkey.retromusic.R.menu
import code.name.monkey.retromusic.dialogs.RemoveFromPlaylistDialog import code.name.monkey.retromusic.dialogs.RemoveFromPlaylistDialog
@ -16,13 +16,16 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags
class OrderablePlaylistSongAdapter( class OrderablePlaylistSongAdapter(
activity: AppCompatActivity, activity: FragmentActivity,
dataSet: ArrayList<Song>, dataSet: ArrayList<Song>,
itemLayoutRes: Int, itemLayoutRes: Int,
cabHolder: CabHolder?, cabHolder: CabHolder?,
private val onMoveItemListener: OnMoveItemListener? private val onMoveItemListener: OnMoveItemListener?
) : PlaylistSongAdapter( ) : SongAdapter(
activity, dataSet, itemLayoutRes, cabHolder activity,
dataSet,
itemLayoutRes,
cabHolder
), DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> { ), DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
init { init {
@ -91,7 +94,7 @@ class OrderablePlaylistSongAdapter(
fun onMoveItem(fromPosition: Int, toPosition: Int) fun onMoveItem(fromPosition: Int, toPosition: Int)
} }
inner class ViewHolder(itemView: View) : PlaylistSongAdapter.ViewHolder(itemView), inner class ViewHolder(itemView: View) : SongAdapter.ViewHolder(itemView),
DraggableItemViewHolder { DraggableItemViewHolder {
@DraggableItemStateFlags @DraggableItemStateFlags
private var mDragStateFlags: Int = 0 private var mDragStateFlags: Int = 0
@ -132,8 +135,4 @@ class OrderablePlaylistSongAdapter(
mDragStateFlags = flags mDragStateFlags = flags
} }
} }
companion object {
val TAG: String = OrderablePlaylistSongAdapter::class.java.simpleName
}
} }

View file

@ -3,6 +3,7 @@ package code.name.monkey.retromusic.adapter.song
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicPlayerRemote.isPlaying import code.name.monkey.retromusic.helper.MusicPlayerRemote.isPlaying
@ -192,7 +193,7 @@ class PlayingQueueAdapter(
internal class SwipedResultActionRemoveItem( internal class SwipedResultActionRemoveItem(
private val adapter: PlayingQueueAdapter, private val adapter: PlayingQueueAdapter,
private val position: Int, private val position: Int,
private val activity: AppCompatActivity private val activity: FragmentActivity
) : SwipeResultActionRemoveItem() { ) : SwipeResultActionRemoveItem() {
private var songToRemove: Song? = null private var songToRemove: Song? = null

View file

@ -1,14 +1,15 @@
package code.name.monkey.retromusic.adapter.song package code.name.monkey.retromusic.adapter.song
import android.app.ActivityOptions
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.navigation.findNavController
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.NavigationUtil
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
open class PlaylistSongAdapter( open class PlaylistSongAdapter(
@ -57,19 +58,14 @@ open class PlaylistSongAdapter(
override fun onSongMenuItemClick(item: MenuItem): Boolean { override fun onSongMenuItemClick(item: MenuItem): Boolean {
if (item.itemId == R.id.action_go_to_album) { if (item.itemId == R.id.action_go_to_album) {
val activityOptions = ActivityOptions.makeSceneTransitionAnimation( activity.findNavController(R.id.fragment_container)
activity, .navigate(
imageContainerCard ?: image, R.id.albumDetailsFragment,
activity.getString(R.string.transition_album_art) bundleOf(EXTRA_ALBUM_ID to song.albumId)
) )
NavigationUtil.goToAlbumOptions(activity, song.albumId, activityOptions)
return true return true
} }
return super.onSongMenuItemClick(item) return super.onSongMenuItemClick(item)
} }
} }
companion object {
val TAG: String = PlaylistSongAdapter::class.java.simpleName
}
} }

View file

@ -2,14 +2,14 @@ package code.name.monkey.retromusic.adapter.song
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import java.util.* import java.util.*
class SimpleSongAdapter( class SimpleSongAdapter(
context: AppCompatActivity, context: FragmentActivity,
songs: ArrayList<Song>, songs: ArrayList<Song>,
layoutRes: Int, layoutRes: Int,
cabHolder: CabHolder? cabHolder: CabHolder?

View file

@ -1,13 +1,15 @@
package code.name.monkey.retromusic.adapter.song package code.name.monkey.retromusic.adapter.song
import android.app.ActivityOptions
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.content.res.Resources import android.content.res.Resources
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
@ -22,7 +24,6 @@ import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil 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.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.afollestad.materialcab.MaterialCab import com.afollestad.materialcab.MaterialCab
@ -34,7 +35,7 @@ import me.zhanghai.android.fastscroll.PopupTextProvider
*/ */
open class SongAdapter( open class SongAdapter(
protected val activity: AppCompatActivity, protected val activity: FragmentActivity,
var dataSet: MutableList<Song>, var dataSet: MutableList<Song>,
protected var itemLayoutRes: Int, protected var itemLayoutRes: Int,
cabHolder: CabHolder?, cabHolder: CabHolder?,
@ -175,12 +176,11 @@ open class SongAdapter(
if (image != null && image!!.visibility == View.VISIBLE) { if (image != null && image!!.visibility == View.VISIBLE) {
when (item.itemId) { when (item.itemId) {
R.id.action_go_to_album -> { R.id.action_go_to_album -> {
val activityOptions = ActivityOptions.makeSceneTransitionAnimation( activity.findNavController(R.id.fragment_container)
activity, .navigate(
imageContainerCard ?: image, R.id.albumDetailsFragment,
activity.getString(R.string.transition_album_art) bundleOf(EXTRA_ALBUM_ID to song.albumId)
) )
NavigationUtil.goToAlbumOptions(activity, song.albumId, activityOptions)
return true return true
} }
} }

View file

@ -22,13 +22,16 @@ import android.widget.Button
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.SeekBar import android.widget.SeekBar
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.App import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
fun Int.ripAlpha(): Int { fun Int.ripAlpha(): Int {
return ColorUtil.stripAlpha(this) return ColorUtil.stripAlpha(this)
@ -84,3 +87,19 @@ fun SeekBar.addAccentColor() {
fun Button.accentTextColor() { fun Button.accentTextColor() {
setTextColor(ThemeStore.accentColor(App.getContext())) setTextColor(ThemeStore.accentColor(App.getContext()))
} }
fun SeekBar.applyColor(@ColorInt color: Int) {
thumbTintList = ColorStateList.valueOf(color)
progressTintList = ColorStateList.valueOf(color)
progressBackgroundTintList = ColorStateList.valueOf(color)
}
fun ExtendedFloatingActionButton.accentColor() {
val color = ThemeStore.accentColor(context)
val textColor = MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(color))
val colorStateList = ColorStateList.valueOf(color)
val textColorStateList = ColorStateList.valueOf(textColor)
backgroundTintList = colorStateList
setTextColor(textColorStateList)
iconTint = textColorStateList
}

View file

@ -0,0 +1,20 @@
package code.name.monkey.retromusic.extensions
import android.app.Activity
import androidx.annotation.DimenRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
fun AppCompatActivity.dimToPixel(@DimenRes dimenRes: Int): Int {
return resources.getDimensionPixelSize(dimenRes)
}
fun Activity.dipToPix(dpInFloat: Float): Float {
val scale = resources.displayMetrics.density
return dpInFloat * scale + 0.5f
}
fun Fragment.dipToPix(dpInFloat: Float): Float {
val scale = resources.displayMetrics.density
return dpInFloat * scale + 0.5f
}

View file

@ -3,7 +3,10 @@ package code.name.monkey.retromusic.extensions
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import android.os.PowerManager import android.os.PowerManager
import android.widget.Toast
import androidx.annotation.IdRes
import androidx.annotation.IntegerRes import androidx.annotation.IntegerRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
@ -53,3 +56,17 @@ fun AppCompatActivity.currentFragment(navHostId: Int): Fragment? {
navHostFragment.targetFragment navHostFragment.targetFragment
return navHostFragment?.childFragmentManager?.fragments?.first() return navHostFragment?.childFragmentManager?.fragments?.first()
} }
@Suppress("UNCHECKED_CAST")
fun <T> AppCompatActivity.whichFragment(@IdRes id: Int): T {
return supportFragmentManager.findFragmentById(id) as T
}
fun Fragment.showToast(@StringRes stringRes: Int) {
showToast(getString(stringRes))
}
fun Fragment.showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}

View file

@ -4,17 +4,22 @@ import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
fun Fragment.navigate(@IdRes id: Int) = findNavController().navigate(id) fun Fragment.navigate(@IdRes id: Int) = findNavController().navigate(id)
fun Fragment.navController(@IdRes id: Int): NavController { fun Fragment.findNavController(@IdRes id: Int): NavController {
val fragment = childFragmentManager.findFragmentById(id) as NavHostFragment val fragment = childFragmentManager.findFragmentById(id) as NavHostFragment
return fragment.navController return fragment.navController
} }
fun AppCompatActivity.navController(@IdRes id: Int): NavController { fun Fragment.findActivityNavController(@IdRes id: Int): NavController {
return requireActivity().findNavController(id)
}
fun AppCompatActivity.findNavController(@IdRes id: Int): NavController {
val fragment = supportFragmentManager.findFragmentById(id) as NavHostFragment val fragment = supportFragmentManager.findFragmentById(id) as NavHostFragment
return fragment.navController return fragment.navController
} }

View file

@ -48,9 +48,3 @@ fun EditText.appHandleColor(): EditText {
TintHelper.colorHandles(this, ThemeStore.accentColor(context)) TintHelper.colorHandles(this, ThemeStore.accentColor(context))
return this return this
} }
fun SeekBar.applyColor(@ColorInt color: Int) {
thumbTintList = ColorStateList.valueOf(color)
progressTintList = ColorStateList.valueOf(color)
progressBackgroundTintList = ColorStateList.valueOf(color)
}

View file

@ -0,0 +1,11 @@
package code.name.monkey.retromusic.fragments
import androidx.annotation.LayoutRes
import code.name.monkey.retromusic.activities.MainActivity
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
open class MainActivityFragment(@LayoutRes layoutRes: Int) : AbsMusicServiceFragment(layoutRes) {
val mainActivity by lazy {
requireActivity() as MainActivity
}
}

View file

@ -1,4 +1,4 @@
package code.name.monkey.retromusic.activities package code.name.monkey.retromusic.fragments.about
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager

View file

@ -0,0 +1,128 @@
package code.name.monkey.retromusic.fragments.about
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.core.app.ShareCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.ContributorAdapter
import code.name.monkey.retromusic.fragments.MainActivityFragment
import code.name.monkey.retromusic.model.Contributor
import code.name.monkey.retromusic.util.NavigationUtil
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
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
class AboutFragment : MainActivityFragment(R.layout.fragment_about), View.OnClickListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.setSupportActionBar(toolbar)
version.setSummary(getAppVersion())
setUpView()
loadContributors()
}
private val contributorsJson: String?
get() {
val json: String
try {
val inputStream = requireActivity().assets.open("contributors.json")
val size = inputStream.available()
val buffer = ByteArray(size)
inputStream.read(buffer)
inputStream.close()
json = String(buffer, StandardCharsets.UTF_8)
} catch (ex: IOException) {
ex.printStackTrace()
return null
}
return json
}
private fun openUrl(url: String) {
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(url)
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(i)
}
private fun setUpView() {
appGithub.setOnClickListener(this)
faqLink.setOnClickListener(this)
telegramLink.setOnClickListener(this)
appRate.setOnClickListener(this)
appTranslation.setOnClickListener(this)
appShare.setOnClickListener(this)
donateLink.setOnClickListener(this)
instagramLink.setOnClickListener(this)
twitterLink.setOnClickListener(this)
changelog.setOnClickListener(this)
openSource.setOnClickListener(this)
pinterestLink.setOnClickListener(this)
bugReportLink.setOnClickListener(this)
}
override fun onClick(view: View) {
when (view.id) {
R.id.pinterestLink -> openUrl(Constants.PINTEREST)
R.id.faqLink -> openUrl(Constants.FAQ_LINK)
R.id.telegramLink -> openUrl(Constants.APP_TELEGRAM_LINK)
R.id.appGithub -> openUrl(Constants.GITHUB_PROJECT)
R.id.appTranslation -> openUrl(Constants.TRANSLATE)
R.id.appRate -> openUrl(Constants.RATE_ON_GOOGLE_PLAY)
R.id.appShare -> shareApp()
R.id.donateLink -> NavigationUtil.goToSupportDevelopment(requireActivity())
R.id.instagramLink -> openUrl(Constants.APP_INSTAGRAM_LINK)
R.id.twitterLink -> openUrl(Constants.APP_TWITTER_LINK)
R.id.changelog -> openUrl(Constants.TELEGRAM_CHANGE_LOG)
R.id.openSource -> NavigationUtil.goToOpenSource(requireActivity())
R.id.bugReportLink -> NavigationUtil.bugReport(requireActivity())
}
}
private fun getAppVersion(): String {
return try {
val isPro = if (App.isProVersion()) "Pro" else "Free"
val packageInfo =
requireActivity().packageManager.getPackageInfo(requireActivity().packageName, 0)
"${packageInfo.versionName} $isPro"
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
"0.0.0"
}
}
private fun shareApp() {
ShareCompat.IntentBuilder.from(requireActivity()).setType("text/plain")
.setChooserTitle(R.string.share_app)
.setText(String.format(getString(R.string.app_share), requireActivity().packageName))
.startChooser()
}
private fun loadContributors() {
val type = object : TypeToken<List<Contributor>>() {
}.type
val contributors = Gson().fromJson<List<Contributor>>(contributorsJson, type)
val contributorAdapter = ContributorAdapter(contributors)
recyclerView.apply {
layoutManager = LinearLayoutManager(requireContext())
itemAnimator = DefaultItemAnimator()
adapter = contributorAdapter
}
}
}

View file

@ -1,23 +1,25 @@
package code.name.monkey.retromusic.activities.albums package code.name.monkey.retromusic.fragments.albums
import android.app.ActivityOptions
import android.os.Bundle import android.os.Bundle
import android.transition.TransitionInflater
import android.util.Pair
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.util.MaterialUtil import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.extensions.extraNotNull import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment import code.name.monkey.retromusic.fragments.MainActivityFragment
import code.name.monkey.retromusic.glide.AlbumGlideRequest import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
@ -26,60 +28,56 @@ import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.model.LastFmAlbum import code.name.monkey.retromusic.network.model.LastFmAlbum
import code.name.monkey.retromusic.util.MusicUtil 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.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_album.*
import kotlinx.android.synthetic.main.activity_album_content.* import kotlinx.android.synthetic.main.activity_album_content.*
import kotlinx.android.synthetic.main.activity_album_details.*
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
import java.util.* import java.util.*
class AlbumDetailsFragment : AbsMusicServiceFragment(R.layout.fragment_album_details) { class AlbumDetailsFragment : MainActivityFragment(R.layout.fragment_album_details),
AlbumClickListener {
private lateinit var simpleSongAdapter: SimpleSongAdapter private lateinit var simpleSongAdapter: SimpleSongAdapter
private lateinit var album: Album private lateinit var album: Album
private val savedSortOrder: String private val savedSortOrder: String
get() = PreferenceUtil.albumDetailSongSortOrder get() = PreferenceUtil.albumDetailSongSortOrder
private val detailsViewModel by viewModel<AlbumDetailsViewModel> {
parametersOf(extraNotNull<Int>(AlbumDetailsActivity.EXTRA_ALBUM_ID).value)
}
private fun setSharedElementTransitionOnEnter() { private val detailsViewModel by viewModel<AlbumDetailsViewModel> {
sharedElementEnterTransition = TransitionInflater.from(context) parametersOf(extraNotNull<Int>(EXTRA_ALBUM_ID).value)
.inflateTransition(R.transition.change_bounds)
} }
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
setSharedElementTransitionOnEnter() mainActivity.setSupportActionBar(toolbar)
mainActivity.setBottomBarVisibility(View.GONE)
toolbar.title = null
postponeEnterTransition() postponeEnterTransition()
playerActivity?.addMusicServiceEventListener(detailsViewModel) playerActivity?.addMusicServiceEventListener(detailsViewModel)
detailsViewModel.getAlbum().observe(viewLifecycleOwner, Observer {
detailsViewModel.getAlbum().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
startPostponedEnterTransition() startPostponedEnterTransition()
showAlbum(it) showAlbum(it)
}) })
detailsViewModel.getArtist().observe(viewLifecycleOwner, androidx.lifecycle.Observer { detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
loadArtistImage(it) loadArtistImage(it)
}) })
detailsViewModel.getMoreAlbums().observe(viewLifecycleOwner, androidx.lifecycle.Observer { detailsViewModel.getMoreAlbums().observe(viewLifecycleOwner, Observer {
moreAlbums(it) moreAlbums(it)
}) })
detailsViewModel.getAlbumInfo().observe(viewLifecycleOwner, androidx.lifecycle.Observer { detailsViewModel.getAlbumInfo().observe(viewLifecycleOwner, Observer {
aboutAlbum(it) aboutAlbum(it)
}) })
setupRecyclerView() setupRecyclerView()
artistImage.setOnClickListener { artistImage.setOnClickListener {
val artistPairs = ActivityOptions.makeSceneTransitionAnimation( requireActivity().findNavController(R.id.fragment_container)
requireActivity(), .navigate(
Pair.create( R.id.artistDetailsFragment,
artistImage, bundleOf(EXTRA_ARTIST_ID to album.artistId)
getString(R.string.transition_artist_image)
) )
)
NavigationUtil.goToArtistOptions(requireActivity(), album.artistId, artistPairs)
} }
playAction.setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) } playAction.setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
@ -177,7 +175,7 @@ class AlbumDetailsFragment : AbsMusicServiceFragment(R.layout.fragment_album_det
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName) moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
val albumAdapter = val albumAdapter =
HorizontalAlbumAdapter(requireActivity() as AppCompatActivity, albums, null) HorizontalAlbumAdapter(requireActivity() as AppCompatActivity, albums, null, this)
moreRecyclerView.layoutManager = GridLayoutManager( moreRecyclerView.layoutManager = GridLayoutManager(
requireContext(), requireContext(),
1, 1,
@ -247,4 +245,11 @@ class AlbumDetailsFragment : AbsMusicServiceFragment(R.layout.fragment_album_det
backgroundColor = color.backgroundColor backgroundColor = color.backgroundColor
) )
} }
override fun onAlbumClick(albumId: Int) {
findNavController().navigate(
R.id.albumDetailsFragment,
bundleOf("extra_album_id" to albumId)
)
}
} }

View file

@ -1,4 +1,4 @@
package code.name.monkey.retromusic.activities.albums package code.name.monkey.retromusic.fragments.albums
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData

View file

@ -2,22 +2,20 @@ package code.name.monkey.retromusic.fragments.albums
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.navigation.findNavController
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.AlbumAdapter import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.fragments.ReloadType import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
class AlbumsFragment : class AlbumsFragment :
AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager>(), AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager>(),
MainActivityFragmentCallbacks { AlbumClickListener {
override fun handleBackPress(): Boolean {
return false
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -40,10 +38,11 @@ class AlbumsFragment :
override fun createAdapter(): AlbumAdapter { override fun createAdapter(): AlbumAdapter {
val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet
return AlbumAdapter( return AlbumAdapter(
mainActivity, requireActivity(),
dataSet, dataSet,
itemLayoutRes(), R.layout.item_grid,
mainActivity null,
this
) )
} }
@ -90,12 +89,17 @@ class AlbumsFragment :
companion object { companion object {
@JvmField
var TAG: String = AlbumsFragment::class.java.simpleName
@JvmStatic
fun newInstance(): AlbumsFragment { fun newInstance(): AlbumsFragment {
return AlbumsFragment() return AlbumsFragment()
} }
} }
override fun onAlbumClick(albumId: Int) {
val controller = requireActivity().findNavController(R.id.fragment_container)
controller.navigate(R.id.albumDetailsFragment, bundleOf(EXTRA_ALBUM_ID to albumId))
}
}
interface AlbumClickListener {
fun onAlbumClick(albumId: Int)
} }

View file

@ -0,0 +1,194 @@
package code.name.monkey.retromusic.fragments.artists
import android.os.Bundle
import android.text.Spanned
import android.view.View
import androidx.core.os.bundleOf
import androidx.core.text.HtmlCompat
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.MainActivityFragment
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.model.LastFmArtist
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_artist_content.*
import kotlinx.android.synthetic.main.activity_artist_details.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
import kotlin.collections.ArrayList
class ArtistDetailsFragment : MainActivityFragment(R.layout.fragment_artist_details),
AlbumClickListener {
private var biography: Spanned? = null
private lateinit var artist: Artist
private lateinit var songAdapter: SimpleSongAdapter
private lateinit var albumAdapter: HorizontalAlbumAdapter
private var forceDownload: Boolean = false
private var lang: String? = null
private val detailsViewModel: ArtistDetailsViewModel by viewModel {
parametersOf(extraNotNull<Int>(EXTRA_ARTIST_ID).value)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.setSupportActionBar(toolbar)
mainActivity.setBottomBarVisibility(View.GONE)
toolbar.title = null
postponeEnterTransition()
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
startPostponedEnterTransition()
showArtist(it)
})
detailsViewModel.getArtistInfo().observe(viewLifecycleOwner, Observer {
artistInfo(it)
})
setupRecyclerView()
playAction.apply {
setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
}
shuffleAction.apply {
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) }
}
biographyText.setOnClickListener {
if (biographyText.maxLines == 4) {
biographyText.maxLines = Integer.MAX_VALUE
} else {
biographyText.maxLines = 4
}
}
}
private fun setupRecyclerView() {
albumAdapter = HorizontalAlbumAdapter(requireActivity(), ArrayList(), null, this)
albumRecyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = GridLayoutManager(this.context, 1, GridLayoutManager.HORIZONTAL, false)
adapter = albumAdapter
}
songAdapter = SimpleSongAdapter(requireActivity(), ArrayList(), R.layout.item_song, null)
recyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = LinearLayoutManager(this.context)
adapter = songAdapter
}
}
fun showArtist(artist: Artist) {
this.artist = artist
loadArtistImage(artist)
if (RetroUtil.isAllowedToDownloadMetadata(requireContext())) {
loadBiography(artist.name)
}
artistTitle.text = artist.name
text.text = String.format(
"%s • %s",
MusicUtil.getArtistInfoString(requireContext(), artist),
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs))
)
val songText =
resources.getQuantityString(
R.plurals.albumSongs,
artist.songCount,
artist.songCount
)
val albumText =
resources.getQuantityString(
R.plurals.albums,
artist.songCount,
artist.songCount
)
songTitle.text = songText
albumTitle.text = albumText
songAdapter.swapDataSet(artist.songs)
artist.albums?.let { albumAdapter.swapDataSet(it) }
}
private fun loadBiography(
name: String,
lang: String? = Locale.getDefault().language
) {
biography = null
this.lang = lang
detailsViewModel.loadBiography(name, lang, null)
}
private fun artistInfo(lastFmArtist: LastFmArtist?) {
if (lastFmArtist != null && lastFmArtist.artist != null) {
val bioContent = lastFmArtist.artist.bio.content
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
biographyText.visibility = View.VISIBLE
biographyTitle.visibility = View.VISIBLE
biography = HtmlCompat.fromHtml(bioContent, HtmlCompat.FROM_HTML_MODE_LEGACY)
biographyText.text = biography
if (lastFmArtist.artist.stats.listeners.isNotEmpty()) {
listeners.show()
listenersLabel.show()
scrobbles.show()
scrobblesLabel.show()
listeners.text =
RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat())
scrobbles.text =
RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat())
}
}
}
// If the "lang" parameter is set and no biography is given, retry with default language
if (biography == null && lang != null) {
loadBiography(artist.name, null)
}
}
private fun loadArtistImage(artist: Artist) {
ArtistGlideRequest.Builder.from(Glide.with(requireContext()), artist)
.generatePalette(requireContext()).build()
.dontAnimate().into(object : RetroMusicColoredTarget(image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors)
}
})
}
private fun setColors(color: MediaNotificationProcessor) {
MaterialUtil.tintColor(
button = shuffleAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
MaterialUtil.tintColor(
button = playAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
}
override fun onAlbumClick(albumId: Int) {
findNavController().navigate(
R.id.albumDetailsFragment,
bundleOf("extra_album_id" to albumId)
)
}
}

View file

@ -1,4 +1,4 @@
package code.name.monkey.retromusic.activities.artists package code.name.monkey.retromusic.fragments.artists
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData

View file

@ -2,10 +2,13 @@ package code.name.monkey.retromusic.fragments.artists
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.extensions.findActivityNavController
import code.name.monkey.retromusic.fragments.ReloadType import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
@ -13,7 +16,7 @@ import code.name.monkey.retromusic.util.PreferenceUtil
class ArtistsFragment : class ArtistsFragment :
AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, GridLayoutManager>(), AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, GridLayoutManager>(),
MainActivityFragmentCallbacks { MainActivityFragmentCallbacks, ArtistClickListener {
override fun handleBackPress(): Boolean { override fun handleBackPress(): Boolean {
return false return false
@ -46,10 +49,11 @@ class ArtistsFragment :
override fun createAdapter(): ArtistAdapter { override fun createAdapter(): ArtistAdapter {
val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet
return ArtistAdapter( return ArtistAdapter(
mainActivity, requireActivity(),
dataSet, dataSet,
itemLayoutRes(), R.layout.item_grid_circle,
mainActivity null,
this
) )
} }
@ -91,12 +95,18 @@ class ArtistsFragment :
} }
companion object { companion object {
@JvmField
val TAG: String = ArtistsFragment::class.java.simpleName
@JvmStatic
fun newInstance(): ArtistsFragment { fun newInstance(): ArtistsFragment {
return ArtistsFragment() return ArtistsFragment()
} }
} }
override fun onArtist(artistId: Int) {
val controller = findActivityNavController(R.id.fragment_container)
controller.navigate(R.id.artistDetailsFragment, bundleOf(EXTRA_ARTIST_ID to artistId))
}
}
interface ArtistClickListener {
fun onArtist(artistId: Int)
} }

View file

@ -14,6 +14,10 @@ import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.os.bundleOf
import androidx.navigation.findNavController
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity
@ -86,11 +90,17 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMusicServiceFragme
return true return true
} }
R.id.action_go_to_album -> { R.id.action_go_to_album -> {
NavigationUtil.goToAlbum(requireActivity(), song.albumId) requireActivity().findNavController(R.id.fragment_container).navigate(
R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to song.albumId)
)
return true return true
} }
R.id.action_go_to_artist -> { R.id.action_go_to_artist -> {
NavigationUtil.goToArtist(requireActivity(), song.artistId) requireActivity().findNavController(R.id.fragment_container).navigate(
R.id.artistDetailsFragment,
bundleOf(EXTRA_ARTIST_ID to song.artistId)
)
return true return true
} }
R.id.now_playing -> { R.id.now_playing -> {

View file

@ -7,7 +7,6 @@ import androidx.annotation.NonNull
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.MainActivity
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.DensityUtil import code.name.monkey.retromusic.util.DensityUtil
@ -24,8 +23,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
AppBarLayout.OnOffsetChangedListener { AppBarLayout.OnOffsetChangedListener {
val libraryViewModel: LibraryViewModel by sharedViewModel() val libraryViewModel: LibraryViewModel by sharedViewModel()
val mainActivity: MainActivity
get() = requireActivity() as MainActivity
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
@ -38,7 +36,6 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
mainActivity.addOnAppBarOffsetChangedListener(this)
initLayoutManager() initLayoutManager()
initAdapter() initAdapter()
setUpRecyclerView() setUpRecyclerView()
@ -112,7 +109,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
container.paddingLeft, container.paddingLeft,
container.paddingTop, container.paddingTop,
container.paddingRight, container.paddingRight,
mainActivity.getTotalAppBarScrollingRange() + i i
) )
} }
@ -137,11 +134,6 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
recyclerView.adapter = adapter recyclerView.adapter = adapter
} }
override fun onDestroyView() {
super.onDestroyView()
mainActivity.removeOnAppBarOffsetChangedListener(this)
}
fun recyclerView(): RecyclerView { fun recyclerView(): RecyclerView {
return recyclerView return recyclerView
} }

View file

@ -0,0 +1,76 @@
package code.name.monkey.retromusic.fragments.genres
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.EXTRA_GENRE
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.fragments.MainActivityFragment
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Song
import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
class GenreDetailsFragment : MainActivityFragment(R.layout.fragment_playlist_detail) {
private val detailsViewModel: GenreDetailsViewModel by viewModel {
parametersOf(extraNotNull<Genre>(EXTRA_GENRE).value)
}
private lateinit var genre: Genre
private lateinit var songAdapter: SongAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(toolbar)
setupRecyclerView()
detailsViewModel.getSongs().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
songs(it)
})
detailsViewModel.getGenre().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
genre = it
toolbar?.title = it.name
})
}
private fun setupRecyclerView() {
songAdapter = SongAdapter(requireActivity(), ArrayList(), R.layout.item_list, null)
recyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = LinearLayoutManager(requireContext())
adapter = songAdapter
}
songAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
super.onChanged()
checkIsEmpty()
}
})
}
fun songs(songs: List<Song>) {
songAdapter.swapDataSet(songs)
}
private fun getEmojiByUnicode(unicode: Int): String {
return String(Character.toChars(unicode))
}
private fun checkIsEmpty() {
checkForPadding()
emptyEmoji.text = getEmojiByUnicode(0x1F631)
empty?.visibility = if (songAdapter.itemCount == 0) View.VISIBLE else View.GONE
}
private fun checkForPadding() {
val height = dipToPix(52f).toInt()
recyclerView.setPadding(0, 0, 0, height)
}
}

View file

@ -1,4 +1,4 @@
package code.name.monkey.retromusic.activities.genre package code.name.monkey.retromusic.fragments.genres
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData

View file

@ -49,7 +49,7 @@ class GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager
override fun createAdapter(): GenreAdapter { override fun createAdapter(): GenreAdapter {
val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet
return GenreAdapter(mainActivity, dataSet, R.layout.item_list_no_image) return GenreAdapter(requireActivity(), dataSet, R.layout.item_list_no_image)
} }
override val emptyMessage: Int override val emptyMessage: Int

View file

@ -18,8 +18,11 @@ import android.app.ActivityOptions
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.view.View import android.view.View
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.navigation.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.EXTRA_PLAYLIST
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.HomeAdapter import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
@ -40,7 +43,7 @@ import kotlinx.android.synthetic.main.fragment_banner_home.*
import kotlinx.android.synthetic.main.home_content.* import kotlinx.android.synthetic.main.home_content.*
import org.koin.androidx.viewmodel.ext.android.sharedViewModel import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class BannerHomeFragment : class HomeFragment :
AbsMainActivityFragment(if (PreferenceUtil.isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home), AbsMainActivityFragment(if (PreferenceUtil.isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home),
MainActivityFragmentCallbacks { MainActivityFragmentCallbacks {
@ -73,13 +76,16 @@ class BannerHomeFragment :
} }
lastAdded.setOnClickListener { lastAdded.setOnClickListener {
NavigationUtil.goToPlaylistNew(requireActivity(), LastAddedPlaylist(requireActivity())) requireActivity().findNavController(R.id.fragment_container).navigate(
R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to LastAddedPlaylist(requireActivity()))
)
} }
topPlayed.setOnClickListener { topPlayed.setOnClickListener {
NavigationUtil.goToPlaylistNew( requireActivity().findNavController(R.id.fragment_container).navigate(
requireActivity(), R.id.playlistDetailsFragment,
MyTopTracksPlaylist(requireActivity()) bundleOf(EXTRA_PLAYLIST to MyTopTracksPlaylist(requireActivity()))
) )
} }
@ -88,7 +94,10 @@ class BannerHomeFragment :
} }
history.setOnClickListener { history.setOnClickListener {
NavigationUtil.goToPlaylistNew(requireActivity(), HistoryPlaylist(requireActivity())) requireActivity().findNavController(R.id.fragment_container).navigate(
R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to HistoryPlaylist(requireActivity()))
)
} }
userImage.setOnClickListener { userImage.setOnClickListener {
@ -101,7 +110,7 @@ class BannerHomeFragment :
} }
titleWelcome?.text = String.format("%s", PreferenceUtil.userName) titleWelcome?.text = String.format("%s", PreferenceUtil.userName)
val homeAdapter = HomeAdapter(mainActivity, displayMetrics) val homeAdapter = HomeAdapter(mainActivity)
recyclerView.apply { recyclerView.apply {
layoutManager = LinearLayoutManager(mainActivity) layoutManager = LinearLayoutManager(mainActivity)
adapter = homeAdapter adapter = homeAdapter
@ -133,8 +142,8 @@ class BannerHomeFragment :
const val TAG: String = "BannerHomeFragment" const val TAG: String = "BannerHomeFragment"
@JvmStatic @JvmStatic
fun newInstance(): BannerHomeFragment { fun newInstance(): HomeFragment {
return BannerHomeFragment() return HomeFragment()
} }
} }
} }

View file

@ -0,0 +1,130 @@
package code.name.monkey.retromusic.fragments.library
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.navigation.fragment.findNavController
import androidx.navigation.navOptions
import androidx.navigation.ui.AppBarConfiguration
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.findNavController
import code.name.monkey.retromusic.fragments.MainActivityFragment
import code.name.monkey.retromusic.fragments.folder.FoldersFragment
import code.name.monkey.retromusic.util.PreferenceUtil
import com.google.android.material.appbar.AppBarLayout
import kotlinx.android.synthetic.main.fragment_library.*
class LibraryFragment : MainActivityFragment(R.layout.fragment_library) {
private val navOptions by lazy {
navOptions {
launchSingleTop = true
anim {
enter = R.anim.retro_fragment_open_enter
exit = R.anim.retro_fragment_open_exit
popEnter = R.anim.retro_fragment_close_enter
popExit = R.anim.retro_fragment_close_exit
}
}
}
private val appBarConfiguration by lazy {
AppBarConfiguration(
setOf(
R.id.libraryFragment,
R.id.settingsFragment,
R.id.searchFragment
)
)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setBottomBarVisibility(View.VISIBLE)
mainActivity.setSupportActionBar(toolbar)
setupNavigationController()
}
private fun setupNavigationController() {
val navController = findNavController(R.id.fragment_container)
val navOptions = navOptions {
launchSingleTop = true
anim {
enter = R.anim.retro_fragment_open_enter
exit = R.anim.retro_fragment_open_exit
popEnter = R.anim.retro_fragment_close_enter
popExit = R.anim.retro_fragment_close_exit
}
popUpTo(navController.graph.startDestination) {
inclusive = true
}
}
mainActivity.getBottomNavigationView().setOnNavigationItemSelectedListener {
var handled = false
if (navController.graph.findNode(it.itemId) != null) {
navController.navigate(it.itemId, null, navOptions)
handled = true
}
when (it.itemId) {
R.id.action_folder -> navController.navigate(
R.id.action_folder,
Bundle().apply {
putSerializable(
FoldersFragment.PATH,
PreferenceUtil.startDirectory
)
},
navOptions
)
}
return@setOnNavigationItemSelectedListener handled
}
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(requireActivity(), toolbar)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.menu_main, menu)
ToolbarContentTintHelper.handleOnCreateOptionsMenu(
requireContext(),
toolbar,
menu,
getToolbarBackgroundColor(toolbar)
)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_search -> findNavController().navigate(
R.id.searchFragment,
null,
navOptions
)
R.id.action_settings -> findNavController().navigate(
R.id.settingsFragment,
null,
navOptions
)
}
return super.onOptionsItemSelected(item)
}
fun addOnAppBarOffsetChangedListener(changedListener: AppBarLayout.OnOffsetChangedListener) {
appBarLayout.addOnOffsetChangedListener(changedListener)
}
fun removeOnAppBarOffsetChangedListener(changedListener: AppBarLayout.OnOffsetChangedListener) {
appBarLayout.removeOnOffsetChangedListener(changedListener)
}
fun getTotalAppBarScrollingRange(): Int {
return 0
}
}

View file

@ -4,7 +4,7 @@ import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.NavController import androidx.navigation.NavController
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.navController import code.name.monkey.retromusic.extensions.findNavController
import code.name.monkey.retromusic.fragments.NowPlayingScreen.* import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
@ -15,7 +15,7 @@ class NowPlayingPlayerFragment : Fragment(R.layout.fragment_now_playing_player)
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
val navController = navController(R.id.playerFragmentContainer) val navController = findNavController(R.id.playerFragmentContainer)
updateNowPlaying(navController) updateNowPlaying(navController)
} }

View file

@ -1,6 +1,5 @@
package code.name.monkey.retromusic.fragments.player.full package code.name.monkey.retromusic.fragments.player.full
import android.app.ActivityOptions
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
@ -8,7 +7,10 @@ import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.os.bundleOf
import androidx.navigation.findNavController
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
@ -22,7 +24,6 @@ import code.name.monkey.retromusic.loaders.ArtistLoader
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics
import code.name.monkey.retromusic.model.lyrics.Lyrics import code.name.monkey.retromusic.model.lyrics.Lyrics
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.fragment_full.* import kotlinx.android.synthetic.main.fragment_full.*
@ -150,18 +151,10 @@ class FullPlayerFragment : AbsPlayerFragment(R.layout.fragment_full),
private fun setupArtist() { private fun setupArtist() {
artistImage.setOnClickListener { artistImage.setOnClickListener {
val transitionName = requireActivity().findNavController(R.id.fragment_container)
"${getString(R.string.transition_artist_image)}_${MusicPlayerRemote.currentSong.artistId}" .navigate(
val activityOptions = R.id.artistDetailsFragment,
ActivityOptions.makeSceneTransitionAnimation( bundleOf(EXTRA_ARTIST_ID to MusicPlayerRemote.currentSong.artistId)
requireActivity(),
artistImage,
transitionName
)
NavigationUtil.goToArtistOptions(
requireActivity(),
MusicPlayerRemote.currentSong.artistId,
activityOptions
) )
} }
} }

View file

@ -1,29 +1,23 @@
package code.name.monkey.retromusic.activities.playlist package code.name.monkey.retromusic.fragments.playlists
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuInflater
import android.view.View import android.view.View
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.retromusic.EXTRA_PLAYLIST
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter
import code.name.monkey.retromusic.adapter.song.PlaylistSongAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.extensions.applyToolbar import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.extensions.extraNotNull import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper import code.name.monkey.retromusic.fragments.MainActivityFragment
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.AbsCustomPlaylist import code.name.monkey.retromusic.model.AbsCustomPlaylist
import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.DensityUtil
import code.name.monkey.retromusic.util.PlaylistsUtil import code.name.monkey.retromusic.util.PlaylistsUtil
import code.name.monkey.retromusic.util.RetroColorUtil
import com.afollestad.materialcab.MaterialCab
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
@ -31,63 +25,52 @@ import kotlinx.android.synthetic.main.activity_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder { class PlaylistDetailsFragment : MainActivityFragment(R.layout.fragment_playlist_detail) {
private val viewModel: PlaylistDetailsViewModel by viewModel { private val viewModel: PlaylistDetailsViewModel by viewModel {
parametersOf(extraNotNull<Playlist>(EXTRA_PLAYLIST).value) parametersOf(extraNotNull<Playlist>(EXTRA_PLAYLIST).value)
} }
private lateinit var playlist: Playlist private lateinit var playlist: Playlist
private var cab: MaterialCab? = null
private lateinit var adapter: SongAdapter private lateinit var adapter: SongAdapter
private var wrappedAdapter: RecyclerView.Adapter<*>? = null private var wrappedAdapter: RecyclerView.Adapter<*>? = null
private var recyclerViewDragDropManager: RecyclerViewDragDropManager? = null private var recyclerViewDragDropManager: RecyclerViewDragDropManager? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setDrawUnderStatusBar() super.onViewCreated(view, savedInstanceState)
super.onCreate(savedInstanceState) mainActivity.addMusicServiceEventListener(viewModel)
setStatusbarColorAuto() mainActivity.setSupportActionBar(toolbar)
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
setLightNavigationBar(true)
setBottomBarVisibility(View.GONE)
playlist = extraNotNull<Playlist>(EXTRA_PLAYLIST).value playlist = extraNotNull<Playlist>(EXTRA_PLAYLIST).value
setUpToolBar()
setUpRecyclerView() setUpRecyclerView()
viewModel.getSongs().observe(this, Observer { viewModel.getSongs().observe(viewLifecycleOwner, Observer {
songs(it) songs(it)
}) })
viewModel.getPlaylist().observe(this, Observer { viewModel.getPlaylist().observe(viewLifecycleOwner, Observer {
playlist = it playlist = it
supportActionBar?.title = it.name toolbar.title = it.name
}) })
addMusicServiceEventListener(viewModel)
}
override fun createContentView(): View {
return wrapSlidingMusicPanel(R.layout.activity_playlist_detail)
} }
private fun setUpRecyclerView() { private fun setUpRecyclerView() {
recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.layoutManager = LinearLayoutManager(requireContext())
if (playlist is AbsCustomPlaylist) { if (playlist is AbsCustomPlaylist) {
adapter = PlaylistSongAdapter(this, ArrayList(), R.layout.item_list, this) adapter = SongAdapter(requireActivity(), ArrayList(), R.layout.item_list, null)
recyclerView.adapter = adapter recyclerView.adapter = adapter
} else { } else {
recyclerViewDragDropManager = RecyclerViewDragDropManager() recyclerViewDragDropManager = RecyclerViewDragDropManager()
val animator = RefactoredDefaultItemAnimator() val animator = RefactoredDefaultItemAnimator()
adapter = OrderablePlaylistSongAdapter(this, adapter = OrderablePlaylistSongAdapter(requireActivity(),
ArrayList(), ArrayList(),
R.layout.item_list, R.layout.item_list,
this, null,
object : OrderablePlaylistSongAdapter.OnMoveItemListener { object : OrderablePlaylistSongAdapter.OnMoveItemListener {
override fun onMoveItem(fromPosition: Int, toPosition: Int) { override fun onMoveItem(fromPosition: Int, toPosition: Int) {
if (PlaylistsUtil.moveItem( if (PlaylistsUtil.moveItem(
this@PlaylistDetailActivity, requireContext(),
playlist.id, playlist.id,
fromPosition, fromPosition,
toPosition toPosition
@ -114,58 +97,18 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
}) })
} }
private fun setUpToolBar() { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
applyToolbar(toolbar) super.onCreateOptionsMenu(menu, inflater)
title = playlist.name inflater.inflate(
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(
if (playlist is AbsCustomPlaylist) R.menu.menu_smart_playlist_detail if (playlist is AbsCustomPlaylist) R.menu.menu_smart_playlist_detail
else R.menu.menu_playlist_detail, menu else R.menu.menu_playlist_detail, menu
) )
return super.onCreateOptionsMenu(menu)
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
onBackPressed()
return true
}
}
return PlaylistMenuHelper.handleMenuClick(this, playlist, item)
}
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)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(
ATHUtil.resolveColor(
this,
R.attr.colorSurface
)
)
).start(callback)
return cab!!
}
override fun onBackPressed() {
if (cab != null && cab!!.isActive) {
cab!!.finish()
} else {
recyclerView!!.stopScroll()
super.onBackPressed()
}
}
private fun checkForPadding() { private fun checkForPadding() {
val height = DensityUtil.dip2px(this, 52f) val height = dipToPix(52f)
recyclerView.setPadding(0, 0, 0, (height)) recyclerView.setPadding(0, 0, 0, height.toInt())
} }
private fun checkIsEmpty() { private fun checkIsEmpty() {
@ -216,8 +159,4 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
showEmptyView() showEmptyView()
} }
} }
companion object {
var EXTRA_PLAYLIST = "extra_playlist"
}
} }

View file

@ -1,4 +1,4 @@
package code.name.monkey.retromusic.activities.playlist package code.name.monkey.retromusic.fragments.playlists
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData

View file

@ -1,8 +1,6 @@
package code.name.monkey.retromusic.fragments.playlists package code.name.monkey.retromusic.fragments.playlists
import android.os.Bundle import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.View import android.view.View
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
@ -12,7 +10,7 @@ import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewFragment
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
class PlaylistsFragment : class PlaylistsFragment :
AbsRecyclerViewFragment<PlaylistAdapter, GridLayoutManager>() , AbsRecyclerViewFragment<PlaylistAdapter, GridLayoutManager>(),
MainActivityFragmentCallbacks { MainActivityFragmentCallbacks {
override fun handleBackPress(): Boolean { override fun handleBackPress(): Boolean {
@ -39,26 +37,14 @@ class PlaylistsFragment :
override fun createAdapter(): PlaylistAdapter { override fun createAdapter(): PlaylistAdapter {
return PlaylistAdapter( return PlaylistAdapter(
mainActivity, requireActivity(),
ArrayList(), ArrayList(),
R.layout.item_list, R.layout.item_list,
mainActivity null
) )
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
menu.apply {
removeItem(R.id.action_sort_order)
removeItem(R.id.action_grid_size)
}
}
companion object { companion object {
@JvmField
val TAG: String = PlaylistsFragment::class.java.simpleName
@JvmStatic
fun newInstance(): PlaylistsFragment { fun newInstance(): PlaylistsFragment {
return PlaylistsFragment() return PlaylistsFragment()
} }

View file

@ -19,13 +19,11 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.App import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.SettingsActivity
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.NavigationUtil
@ -78,12 +76,4 @@ class MainSettingsFragment : Fragment(), View.OnClickListener {
diamondIcon.imageTintList = ColorStateList.valueOf(it) diamondIcon.imageTintList = ColorStateList.valueOf(it)
} }
} }
companion object {
}
private fun inflateFragment(fragment: Fragment, @StringRes title: Int) {
(requireActivity() as SettingsActivity).setupFragment(fragment, title)
}
} }

View file

@ -0,0 +1,23 @@
package code.name.monkey.retromusic.fragments.settings
import android.os.Bundle
import android.view.View
import androidx.navigation.NavController
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.findNavController
import code.name.monkey.retromusic.fragments.MainActivityFragment
import kotlinx.android.synthetic.main.fragment_settings.*
class SettingsFragment : MainActivityFragment(R.layout.fragment_settings) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.setSupportActionBar(toolbar)
mainActivity.hideBottomNavigation()
mainActivity.setBottomBarVisibility(View.GONE)
val navController: NavController = findNavController(R.id.contentFrame)
navController.addOnDestinationChangedListener { _, _, _ ->
toolbar.title = navController.currentDestination?.label
}
}
}

View file

@ -1,12 +1,11 @@
package code.name.monkey.retromusic.fragments.songs package code.name.monkey.retromusic.fragments.songs
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.View
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.song.ShuffleButtonSongAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.fragments.ReloadType import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment
@ -36,26 +35,16 @@ class SongsFragment :
get() = R.string.no_songs get() = R.string.no_songs
override fun createLayoutManager(): GridLayoutManager { override fun createLayoutManager(): GridLayoutManager {
return GridLayoutManager(requireActivity(), getGridSize()).apply { return GridLayoutManager(requireActivity(), getGridSize())
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (position == 0) {
getGridSize()
} else {
1
}
}
}
}
} }
override fun createAdapter(): SongAdapter { override fun createAdapter(): SongAdapter {
val dataSet = if (adapter == null) mutableListOf() else adapter!!.dataSet val dataSet = if (adapter == null) mutableListOf() else adapter!!.dataSet
return ShuffleButtonSongAdapter( return SongAdapter(
mainActivity, requireActivity(),
dataSet, dataSet,
itemLayoutRes(), R.layout.item_list,
mainActivity null
) )
} }
@ -109,72 +98,4 @@ class SongsFragment :
return SongsFragment() return SongsFragment()
} }
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
setUpGridSizeMenu(menu.findItem(R.id.action_grid_size).subMenu)
}
private fun setUpGridSizeMenu(
gridSizeMenu: SubMenu
) {
println(getGridSize())
when (getGridSize()) {
1 -> gridSizeMenu.findItem(R.id.action_grid_size_1).isChecked = true
2 -> gridSizeMenu.findItem(R.id.action_grid_size_2).isChecked = true
3 -> gridSizeMenu.findItem(R.id.action_grid_size_3).isChecked = true
4 -> gridSizeMenu.findItem(R.id.action_grid_size_4).isChecked = true
5 -> gridSizeMenu.findItem(R.id.action_grid_size_5).isChecked = true
6 -> gridSizeMenu.findItem(R.id.action_grid_size_6).isChecked = true
7 -> gridSizeMenu.findItem(R.id.action_grid_size_7).isChecked = true
8 -> gridSizeMenu.findItem(R.id.action_grid_size_8).isChecked = true
}
val maxGridSize = maxGridSize
if (maxGridSize < 8) {
gridSizeMenu.findItem(R.id.action_grid_size_8).isVisible = false
}
if (maxGridSize < 7) {
gridSizeMenu.findItem(R.id.action_grid_size_7).isVisible = false
}
if (maxGridSize < 6) {
gridSizeMenu.findItem(R.id.action_grid_size_6).isVisible = false
}
if (maxGridSize < 5) {
gridSizeMenu.findItem(R.id.action_grid_size_5).isVisible = false
}
if (maxGridSize < 4) {
gridSizeMenu.findItem(R.id.action_grid_size_4).isVisible = false
}
if (maxGridSize < 3) {
gridSizeMenu.findItem(R.id.action_grid_size_3).isVisible = false
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (handleGridSizeMenuItem(item)) return true
return super.onOptionsItemSelected(item)
}
fun handleGridSizeMenuItem(
item: MenuItem
): Boolean {
var gridSize = 0
when (item.itemId) {
R.id.action_grid_size_1 -> gridSize = 1
R.id.action_grid_size_2 -> gridSize = 2
R.id.action_grid_size_3 -> gridSize = 3
R.id.action_grid_size_4 -> gridSize = 4
R.id.action_grid_size_5 -> gridSize = 5
R.id.action_grid_size_6 -> gridSize = 6
R.id.action_grid_size_7 -> gridSize = 7
R.id.action_grid_size_8 -> gridSize = 8
}
if (gridSize > 0) {
item.isChecked = true
setAndSaveGridSize(gridSize)
return true
}
return false
}
} }

View file

@ -19,7 +19,7 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.view.MenuItem import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.App import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
@ -38,7 +38,7 @@ import java.util.*
object PlaylistMenuHelper { object PlaylistMenuHelper {
fun handleMenuClick( fun handleMenuClick(
activity: AppCompatActivity, activity: FragmentActivity,
playlist: Playlist, item: MenuItem playlist: Playlist, item: MenuItem
): Boolean { ): Boolean {
when (item.itemId) { when (item.itemId) {

View file

@ -18,8 +18,11 @@ import android.content.Intent
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.PopupMenu import android.widget.PopupMenu
import androidx.appcompat.app.AppCompatActivity import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity
@ -30,7 +33,6 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.PaletteColorHolder import code.name.monkey.retromusic.interfaces.PaletteColorHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.RingtoneManager import code.name.monkey.retromusic.util.RingtoneManager
object SongMenuHelper { object SongMenuHelper {
@ -89,18 +91,24 @@ object SongMenuHelper {
return true return true
} }
R.id.action_go_to_album -> { R.id.action_go_to_album -> {
NavigationUtil.goToAlbum(activity, song.albumId) activity.findNavController(R.id.fragment_container).navigate(
R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to song.albumId)
)
return true return true
} }
R.id.action_go_to_artist -> { R.id.action_go_to_artist -> {
NavigationUtil.goToArtist(activity, song.artistId) activity.findNavController(R.id.fragment_container).navigate(
R.id.artistDetailsFragment,
bundleOf(EXTRA_ARTIST_ID to song.artistId)
)
return true return true
} }
} }
return false return false
} }
abstract class OnClickSongMenu protected constructor(private val activity: AppCompatActivity) : abstract class OnClickSongMenu(private val activity: FragmentActivity) :
View.OnClickListener, PopupMenu.OnMenuItemClickListener { View.OnClickListener, PopupMenu.OnMenuItemClickListener {
open val menuRes: Int open val menuRes: Int

View file

@ -67,7 +67,7 @@ object PlaylistSongsLoader {
val artistName = cursor.getString(10) val artistName = cursor.getString(10)
val idInPlaylist = cursor.getInt(11) val idInPlaylist = cursor.getInt(11)
val composer = cursor.getString(12) val composer = cursor.getString(12)
val albumArtist = cursor.getString(13)
return PlaylistSong( return PlaylistSong(
id, id,
title, title,
@ -82,7 +82,8 @@ object PlaylistSongsLoader {
artistName, artistName,
playlistId, playlistId,
idInPlaylist, idInPlaylist,
composer composer,
albumArtist
) )
} }
@ -103,10 +104,9 @@ object PlaylistSongsLoader {
AudioColumns.ARTIST_ID, // 9 AudioColumns.ARTIST_ID, // 9
AudioColumns.ARTIST, // 10 AudioColumns.ARTIST, // 10
MediaStore.Audio.Playlists.Members._ID,//11 MediaStore.Audio.Playlists.Members._ID,//11
AudioColumns.COMPOSER AudioColumns.COMPOSER,//12
)// 12 "album_artist"//13
, IS_MUSIC, null, ), IS_MUSIC, null, MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER
) )
} catch (e: SecurityException) { } catch (e: SecurityException) {
return null return null

View file

@ -95,10 +95,21 @@ object SongLoader {
val artistId = cursor.getInt(9) val artistId = cursor.getInt(9)
val artistName = cursor.getString(10) val artistName = cursor.getString(10)
val composer = cursor.getString(11) val composer = cursor.getString(11)
val albumArtist = cursor.getString(12)
return Song( return Song(
id, title, trackNumber, year, duration, data, dateModified, albumId, id,
albumName ?: "", artistId, artistName, composer ?: "" title,
trackNumber,
year,
duration,
data,
dateModified,
albumId,
albumName ?: "",
artistId,
artistName ?: "",
composer ?: "",
albumArtist ?: ""
) )
} }
@ -123,13 +134,13 @@ object SongLoader {
selectionFinal = generateBlacklistSelection(selectionFinal, paths.size) selectionFinal = generateBlacklistSelection(selectionFinal, paths.size)
selectionValuesFinal = addBlacklistSelectionValues(selectionValuesFinal, paths) selectionValuesFinal = addBlacklistSelectionValues(selectionValuesFinal, paths)
} }
selectionFinal =
selectionFinal + " AND " + MediaStore.Audio.Media.DURATION + ">= " + (PreferenceUtil.filterLength * 1000)
try { try {
return context.contentResolver.query( return context.contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
baseProjection, baseProjection,
selectionFinal + " AND " + MediaStore.Audio.Media.DURATION + ">= " + selectionFinal,
(PreferenceUtil.filterLength * 1000),
selectionValuesFinal, selectionValuesFinal,
sortOrder sortOrder
) )

View file

@ -59,9 +59,9 @@ public class CategoryInfo implements Parcelable {
} }
public enum Category { public enum Category {
Home(R.id.action_home, R.string.home, R.drawable.asld_home), Home(R.id.action_home, R.string.for_you, R.drawable.ic_baseline),
Songs(R.id.action_song, R.string.songs, R.drawable.asld_music_note), Songs(R.id.action_song, R.string.songs, R.drawable.ic_audiotrack),
Albums(R.id.action_album, R.string.albums, R.drawable.asld_album), Albums(R.id.action_album, R.string.albums, R.drawable.ic_album),
Artists(R.id.action_artist, R.string.artists, R.drawable.ic_artist), Artists(R.id.action_artist, R.string.artists, R.drawable.ic_artist),
Playlists(R.id.action_playlist, R.string.playlists, R.drawable.ic_playlist_play), Playlists(R.id.action_playlist, R.string.playlists, R.drawable.ic_playlist_play),
Genres(R.id.action_genre, R.string.genres, R.drawable.ic_guitar), Genres(R.id.action_genre, R.string.genres, R.drawable.ic_guitar),

View file

@ -41,9 +41,9 @@ public class PlaylistSong extends Song {
@NotNull String artistName, @NotNull String artistName,
int playlistId, int playlistId,
int idInPlayList, int idInPlayList,
@NotNull String composer) { @NotNull String composer,
super(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName, String albumArtist) {
composer); super(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName, composer, albumArtist);
this.playlistId = playlistId; this.playlistId = playlistId;
this.idInPlayList = idInPlayList; this.idInPlayList = idInPlayList;
} }

View file

@ -29,7 +29,8 @@ open class Song(
val albumName: String, val albumName: String,
val artistId: Int, val artistId: Int,
val artistName: String, val artistName: String,
val composer: String? val composer: String?,
val albumArtist: String?
) : Parcelable { ) : Parcelable {
@ -48,6 +49,7 @@ open class Song(
"", "",
-1, -1,
"", "",
"",
"" ""
) )
} }

View file

@ -43,7 +43,7 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper {
public static final String ORIGINAL_PLAYING_QUEUE_TABLE_NAME = "original_playing_queue"; public static final String ORIGINAL_PLAYING_QUEUE_TABLE_NAME = "original_playing_queue";
private static final int VERSION = 10; private static final int VERSION = 12;
@Nullable @Nullable
private static MusicPlaybackQueueStore sInstance = null; private static MusicPlaybackQueueStore sInstance = null;
@ -148,6 +148,9 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper {
builder.append(" STRING NOT NULL,"); builder.append(" STRING NOT NULL,");
builder.append(AudioColumns.COMPOSER); builder.append(AudioColumns.COMPOSER);
builder.append(" STRING,");
builder.append("album_artist");
builder.append(" STRING);"); builder.append(" STRING);");
db.execSQL(builder.toString()); db.execSQL(builder.toString());

View file

@ -14,12 +14,15 @@
package code.name.monkey.retromusic.util package code.name.monkey.retromusic.util
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.widget.Toast
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.play.core.review.ReviewManagerFactory
object AppRater { object AppRater {
private const val DO_NOT_SHOW_AGAIN = "do_not_show_again"// Package Name private const val DO_NOT_SHOW_AGAIN = "do_not_show_again"// Package Name
@ -53,13 +56,29 @@ object AppRater {
// Wait at least n days before opening // Wait at least n days before opening
if (launchCount >= LAUNCHES_UNTIL_PROMPT) { if (launchCount >= LAUNCHES_UNTIL_PROMPT) {
if (System.currentTimeMillis() >= dateFirstLaunch + DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000) { if (System.currentTimeMillis() >= dateFirstLaunch + DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000) {
showRateDialog(context, editor) //showRateDialog(context, editor)
showPlayStoreReviewDialog(context)
} }
} }
editor.commit() editor.commit()
} }
private fun showPlayStoreReviewDialog(context: Context) {
val manager = ReviewManagerFactory.create(context)
manager.requestReviewFlow().addOnCompleteListener { request ->
if (request.isSuccessful) {
val reviewInfo = request.result
manager.launchReviewFlow(context as Activity, reviewInfo).addOnCompleteListener {
if (it.isSuccessful) {
Toast.makeText(context, "Thanks for the feedback", Toast.LENGTH_SHORT)
.show()
}
}
}
}
}
private fun showRateDialog(context: Context, editor: SharedPreferences.Editor) { private fun showRateDialog(context: Context, editor: SharedPreferences.Editor) {
MaterialAlertDialogBuilder(context) MaterialAlertDialogBuilder(context)
.setTitle("Rate this App") .setTitle("Rate this App")

View file

@ -28,28 +28,16 @@ import androidx.core.app.ActivityCompat;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.activities.AboutActivity;
import code.name.monkey.retromusic.activities.DriveModeActivity; import code.name.monkey.retromusic.activities.DriveModeActivity;
import code.name.monkey.retromusic.activities.genre.GenreDetailsActivity;
import code.name.monkey.retromusic.activities.LicenseActivity; import code.name.monkey.retromusic.activities.LicenseActivity;
import code.name.monkey.retromusic.activities.LyricsActivity; import code.name.monkey.retromusic.activities.LyricsActivity;
import code.name.monkey.retromusic.activities.PlayingQueueActivity; import code.name.monkey.retromusic.activities.PlayingQueueActivity;
import code.name.monkey.retromusic.activities.playlist.PlaylistDetailActivity;
import code.name.monkey.retromusic.activities.PurchaseActivity; import code.name.monkey.retromusic.activities.PurchaseActivity;
import code.name.monkey.retromusic.activities.search.SearchActivity;
import code.name.monkey.retromusic.activities.SettingsActivity;
import code.name.monkey.retromusic.activities.SupportDevelopmentActivity; import code.name.monkey.retromusic.activities.SupportDevelopmentActivity;
import code.name.monkey.retromusic.activities.UserInfoActivity; import code.name.monkey.retromusic.activities.UserInfoActivity;
import code.name.monkey.retromusic.activities.WhatsNewActivity; import code.name.monkey.retromusic.activities.WhatsNewActivity;
import code.name.monkey.retromusic.activities.albums.AlbumDetailsActivity;
import code.name.monkey.retromusic.activities.artists.ArtistDetailActivity;
import code.name.monkey.retromusic.activities.bugreport.BugReportActivity; import code.name.monkey.retromusic.activities.bugreport.BugReportActivity;
import code.name.monkey.retromusic.helper.MusicPlayerRemote; import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Playlist;
import static code.name.monkey.retromusic.Constants.RATE_ON_GOOGLE_PLAY;
import static code.name.monkey.retromusic.util.RetroUtil.openUrl;
public class NavigationUtil { public class NavigationUtil {
@ -58,45 +46,6 @@ public class NavigationUtil {
ActivityCompat.startActivity(activity, new Intent(activity, BugReportActivity.class), null); ActivityCompat.startActivity(activity, new Intent(activity, BugReportActivity.class), null);
} }
public static void goToAbout(@NonNull Activity activity) {
ActivityCompat.startActivity(activity, new Intent(activity, AboutActivity.class), null);
}
public static void goToAlbum(@NonNull Activity activity, int albumId) {
Intent intent = new Intent(activity, AlbumDetailsActivity.class);
intent.putExtra(AlbumDetailsActivity.EXTRA_ALBUM_ID, albumId);
ActivityCompat.startActivity(activity, intent, null);
}
public static void goToAlbumOptions(@NonNull Activity activity,
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());
}
public static void goToArtist(@NonNull Activity activity, int i) {
Intent intent = new Intent(activity, ArtistDetailActivity.class);
intent.putExtra(ArtistDetailActivity.EXTRA_ARTIST_ID, i);
ActivityCompat.startActivity(activity, intent, null);
}
public static void goToArtistOptions(@NotNull Activity activity,
int artistId,
@NonNull ActivityOptions options) {
Intent intent = new Intent(activity, ArtistDetailActivity.class);
intent.putExtra(ArtistDetailActivity.EXTRA_ARTIST_ID, artistId);
ActivityCompat.startActivity(activity, intent, options.toBundle());
}
public static void goToGenre(@NonNull Activity activity, @NonNull Genre genre) {
Intent intent = new Intent(activity, GenreDetailsActivity.class);
intent.putExtra(GenreDetailsActivity.EXTRA_GENRE_ID, genre);
ActivityCompat.startActivity(activity, intent, null);
}
public static void goToLyrics(@NonNull Activity activity) { public static void goToLyrics(@NonNull Activity activity) {
Intent intent = new Intent(activity, LyricsActivity.class); Intent intent = new Intent(activity, LyricsActivity.class);
ActivityCompat.startActivity(activity, intent, null); ActivityCompat.startActivity(activity, intent, null);
@ -106,47 +55,15 @@ public class NavigationUtil {
ActivityCompat.startActivity(activity, new Intent(activity, LicenseActivity.class), null); ActivityCompat.startActivity(activity, new Intent(activity, LicenseActivity.class), null);
} }
public static void goToPlayStore(@NonNull Activity activity) {
openUrl(activity, RATE_ON_GOOGLE_PLAY);
}
public static void goToPlayingQueue(@NonNull Activity activity) { public static void goToPlayingQueue(@NonNull Activity activity) {
Intent intent = new Intent(activity, PlayingQueueActivity.class); Intent intent = new Intent(activity, PlayingQueueActivity.class);
ActivityCompat.startActivity(activity, intent, null); ActivityCompat.startActivity(activity, intent, null);
} }
public static void goToPlaylistNew(@NonNull Activity activity, @NonNull Playlist playlist) {
Intent intent = new Intent(activity, PlaylistDetailActivity.class);
intent.putExtra(PlaylistDetailActivity.Companion.getEXTRA_PLAYLIST(), playlist);
ActivityCompat.startActivity(activity, intent, null);
}
public static void goToProVersion(@NonNull Context context) { public static void goToProVersion(@NonNull Context context) {
ActivityCompat.startActivity(context, new Intent(context, PurchaseActivity.class), null); ActivityCompat.startActivity(context, new Intent(context, PurchaseActivity.class), null);
} }
public static void goToSearch(@NonNull Activity activity,
@NonNull ActivityOptions activityOptions) {
ActivityCompat.startActivity(activity, new Intent(activity, SearchActivity.class),
activityOptions.toBundle());
}
public static void goToSearch(@NonNull Activity activity) {
ActivityCompat.startActivity(activity, new Intent(activity, SearchActivity.class),
null);
}
public static void goToSearch(@NonNull Activity activity, boolean isMicOpen,
@NonNull ActivityOptions activityOptions) {
ActivityCompat.startActivity(activity, new Intent(activity, SearchActivity.class)
.putExtra(SearchActivity.EXTRA_SHOW_MIC, isMicOpen),
activityOptions.toBundle());
}
public static void goToSettings(@NonNull Activity activity) {
ActivityCompat.startActivity(activity, new Intent(activity, SettingsActivity.class), null);
}
public static void goToSupportDevelopment(@NonNull Activity activity) { public static void goToSupportDevelopment(@NonNull Activity activity) {
ActivityCompat.startActivity(activity, new Intent(activity, SupportDevelopmentActivity.class), null); ActivityCompat.startActivity(activity, new Intent(activity, SupportDevelopmentActivity.class), null);
} }

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,11.75c-0.69,0 -1.25,0.56 -1.25,1.25s0.56,1.25 1.25,1.25 1.25,-0.56 1.25,-1.25 -0.56,-1.25 -1.25,-1.25zM15,11.75c-0.69,0 -1.25,0.56 -1.25,1.25s0.56,1.25 1.25,1.25 1.25,-0.56 1.25,-1.25 -0.56,-1.25 -1.25,-1.25zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8 0,-0.29 0.02,-0.58 0.05,-0.86 2.36,-1.05 4.23,-2.98 5.21,-5.37C11.07,8.33 14.05,10 17.42,10c0.78,0 1.53,-0.09 2.25,-0.26 0.21,0.71 0.33,1.47 0.33,2.26 0,4.41 -3.59,8 -8,8z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M4,11h5L9,5L4,5v6zM4,18h5v-6L4,12v6zM10,18h5v-6h-5v6zM16,18h5v-6h-5v6zM10,11h5L15,5h-5v6zM16,5v6h5L21,5h-5z"/>
</vector>

View file

@ -1,61 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?colorSurface"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="0dp"
tools:ignore="UnusedAttribute">
<include layout="@layout/status_bar" />
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/mainContent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
app:popupTheme="?attr/toolbarPopupTheme"
app:title="@string/app_name"
app:titleTextAppearance="@style/ToolbarTextAppearanceNormal.Library"
app:titleTextColor="?attr/colorControlNormal"
tools:ignore="UnusedAttribute" />
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container" android:id="@+id/fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
tools:layout="@layout/fragment_main_activity_recycler_view" /> app:navGraph="@navigation/main_graph" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<include layout="@layout/activity_about_content" />
</androidx.core.widget.NestedScrollView>

View file

@ -1,10 +1,48 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:orientation="vertical"
tools:ignore="UnusedAttribute">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/status_bar" />
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
android:background="?attr/colorSurface"
app:navigationIcon="@drawable/ic_keyboard_backspace_black" />
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="48dp" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/container" android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -99,4 +137,5 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:orientation="vertical"
tools:ignore="UnusedAttribute">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/status_bar" />
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
android:background="?attr/colorSurface"
app:navigationIcon="@drawable/ic_keyboard_backspace_black" />
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="48dp" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:id="@+id/artistCoverContainer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:transitionName="@string/transition_artist_image"
app:cardCornerRadius="24dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
</com.google.android.material.card.MaterialCardView>
<code.name.monkey.retromusic.views.BaselineGridTextView
android:id="@+id/artistTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:maxLines="2"
android:textAppearance="@style/TextViewHeadline5"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/artistCoverContainer"
tools:ignore="MissingPrefix"
tools:text="@tools:sample/full_names" />
<code.name.monkey.retromusic.views.BaselineGridTextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:textAppearance="@style/TextViewSubtitle2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/artistTitle"
tools:ignore="MissingPrefix"
tools:text="@tools:sample/full_names" />
<include
layout="@layout/activity_artist_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View file

@ -1,17 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- <?xml version="1.0" encoding="utf-8"?>
~ 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -31,6 +18,7 @@
</FrameLayout> </FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/mainContent"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -38,32 +26,22 @@
android:id="@+id/appBarLayout" android:id="@+id/appBarLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:elevation="0dp"
app:elevation="0dp"
app:liftOnScroll="true"> app:liftOnScroll="true">
<com.google.android.material.card.MaterialCardView
android:id="@+id/toolbarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardUseCompatPadding="true"
app:layout_scrollFlags="scroll|enterAlways">
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
<androidx.appcompat.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" android:layout_height="wrap_content"
android:background="?colorSurface" android:background="?attr/colorSurface"
app:popupTheme="?attr/toolbarPopupTheme" app:popupTheme="?attr/toolbarPopupTheme"
app:title="@string/action_search" app:title="@string/app_name"
app:titleTextAppearance="@style/TextViewHeadline6" app:titleTextAppearance="@style/ToolbarTextAppearanceNormal.Library"
app:titleTextColor="?android:attr/textColorSecondary" app:titleTextColor="?attr/colorControlNormal"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute" />
<ViewStub <ViewStub
@ -71,14 +49,15 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" /> android:layout_height="@dimen/toolbar_height" />
</FrameLayout> </FrameLayout>
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<FrameLayout <androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainer" android:id="@+id/fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> app:defaultNavHost="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:navGraph="@navigation/library_graph" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout> </LinearLayout>

View file

@ -58,6 +58,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
app:defaultNavHost="true" app:defaultNavHost="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:navGraph="@navigation/retro_graph" /> app:navGraph="@navigation/main_graph" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout> </LinearLayout>

View file

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:orientation="vertical"
tools:ignore="UnusedAttribute">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/status_bar" />
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
app:navigationIcon="@drawable/ic_keyboard_backspace_black"
app:titleTextAppearance="@style/ToolbarTextAppearanceNormal" />
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="48dp" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:overScrollMode="never"
android:scrollbars="none"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
<LinearLayout
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/emptyEmoji"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/empty_text_emoji"
android:textAppearance="@style/TextViewHeadline3" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/emptyText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/no_songs"
android:textAppearance="@style/TextViewHeadline5"
android:textColor="?android:attr/textColorSecondary"
tools:visibility="visible" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View file

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<code.name.monkey.retromusic.views.StatusBarView
android:id="@+id/status_bar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="?attr/colorSurface"
tools:ignore="UnusedAttribute" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
app:liftOnScroll="true">
<com.google.android.material.appbar.MaterialToolbar
android:layout_width="match_parent"
android:id="@+id/toolbar"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
android:layout_weight="1"
android:background="@null"
android:hint="@string/action_search"
android:inputType="text|textAutoComplete"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textAppearance="@style/TextViewSubtitle1">
<requestFocus />
</com.google.android.material.textfield.TextInputEditText>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/voiceSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?roundSelector"
android:padding="12dp"
app:srcCompat="@drawable/ic_mic"
app:tint="?attr/colorControlNormal"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/clearText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?roundSelector"
android:padding="12dp"
android:visibility="gone"
app:srcCompat="@drawable/ic_close"
app:tint="?attr/colorControlNormal"
tools:visibility="visible" />
</FrameLayout>
</LinearLayout>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.textview.MaterialTextView
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/no_results"
android:textAppearance="@style/TextViewHeadline6"
android:visibility="gone"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:overScrollMode="never"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/keyboardPopup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginEnd="16dp"
android:layout_marginBottom="62dp"
android:text="@string/keyboard"
android:textAppearance="@style/TextViewHeadline6"
app:icon="@drawable/ic_keyboard" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<code.name.monkey.retromusic.views.StatusBarView
android:id="@+id/status_bar"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:ignore="UnusedAttribute" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface">
<androidx.core.widget.NestedScrollView
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/contentFrame"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:defaultNavHost="true"
app:navGraph="@navigation/settings_graph" />
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
app:liftOnScroll="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_keyboard_backspace_black"
app:titleTextAppearance="@style/ToolbarTextAppearanceNormal"
tools:title="@string/action_settings" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View file

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="1dp"
android:background="?attr/rectSelector" android:background="?attr/rectSelector"
android:clickable="true" android:clickable="true"
android:focusable="true"> android:focusable="true">
@ -11,7 +12,7 @@
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="6dp" android:layout_margin="5dp"
app:cardCornerRadius="8dp" app:cardCornerRadius="8dp"
tools:ignore="MissingPrefix"> tools:ignore="MissingPrefix">

View file

@ -4,15 +4,15 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="4dp" android:layout_margin="1dp"
android:background="?attr/rectSelector" android:background="?attr/rectSelector"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true">
tools:ignore="MissingPrefix">
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardCornerRadius="8dp" app:cardCornerRadius="8dp"
tools:ignore="MissingPrefix"> tools:ignore="MissingPrefix">
@ -33,7 +33,6 @@
tools:ignore="ContentDescription" tools:ignore="ContentDescription"
tools:src="@tools:sample/avatars" /> tools:src="@tools:sample/avatars" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -16,7 +16,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:gravity="center_vertical|end"
android:orientation="horizontal"> android:orientation="horizontal">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
@ -27,6 +27,7 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:layout_weight="1" android:layout_weight="1"
android:text="@string/action_play_all" android:text="@string/action_play_all"
android:visibility="gone"
app:backgroundTint="?attr/colorSurface" app:backgroundTint="?attr/colorSurface"
app:icon="@drawable/ic_play_arrow" /> app:icon="@drawable/ic_play_arrow" />
@ -38,7 +39,35 @@
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_weight="1" android:layout_weight="1"
android:text="@string/shuffle" android:text="@string/shuffle"
android:visibility="gone"
app:backgroundTint="?attr/colorSurface" app:backgroundTint="?attr/colorSurface"
app:icon="@drawable/ic_shuffle" /> app:icon="@drawable/ic_shuffle" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/songsMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:padding="16dp"
app:srcCompat="@drawable/ic_sort"
app:tint="?attr/colorControlNormal" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/gridMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:padding="16dp"
app:srcCompat="@drawable/ic_grid_size"
app:tint="?attr/colorControlNormal" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:padding="16dp"
app:srcCompat="@drawable/ic_layout"
app:tint="?attr/colorControlNormal" />
</LinearLayout> </LinearLayout>

View file

@ -30,11 +30,11 @@
<androidx.fragment.app.FragmentContainerView <androidx.fragment.app.FragmentContainerView
android:id="@+id/playerFragmentContainer" android:id="@+id/playerFragmentContainer"
android:layout_width="match_parent"
android:name="code.name.monkey.retromusic.fragments.player.NowPlayingPlayerFragment" android:name="code.name.monkey.retromusic.fragments.player.NowPlayingPlayerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<androidx.fragment.app.FragmentContainerView <fragment
android:id="@+id/miniPlayerFragment" android:id="@+id/miniPlayerFragment"
android:name="code.name.monkey.retromusic.fragments.MiniPlayerFragment" android:name="code.name.monkey.retromusic.fragments.MiniPlayerFragment"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -16,84 +16,15 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".DrawerActivity"> tools:context=".DrawerActivity">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search"
android:title="@string/action_search"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/action_grid_size" android:id="@+id/action_settings"
android:icon="@drawable/ic_grid_size" android:icon="@drawable/ic_settings"
android:orderInCategory="5" android:title="@string/action_settings"
android:title="@string/action_grid_size" app:showAsAction="ifRoom" />
app:showAsAction="ifRoom">
<menu>
<group
android:id="@+id/group_grid_size"
android:checkableBehavior="single">
<item
android:id="@+id/action_grid_size_1"
android:title="@string/grid_size_1" />
<item
android:id="@+id/action_grid_size_2"
android:title="@string/grid_size_2" />
<item
android:id="@+id/action_grid_size_3"
android:title="@string/grid_size_3" />
<item
android:id="@+id/action_grid_size_4"
android:title="@string/grid_size_4" />
<item
android:id="@+id/action_grid_size_5"
android:title="@string/grid_size_5" />
<item
android:id="@+id/action_grid_size_6"
android:title="@string/grid_size_6" />
<item
android:id="@+id/action_grid_size_7"
android:title="@string/grid_size_7" />
<item
android:id="@+id/action_grid_size_8"
android:title="@string/grid_size_8" />
</group>
</menu>
</item>
<item
android:id="@+id/action_layout_type"
android:icon="@drawable/ic_dashboard"
android:orderInCategory="6"
android:title="@string/grid_style_label"
app:showAsAction="ifRoom">
<menu>
<group
android:id="@+id/group_layout_type"
android:checkableBehavior="single">
<item
android:id="@+id/action_layout_normal"
android:checked="true"
android:title="@string/normal" />
<item
android:id="@+id/action_layout_card"
android:title="@string/card" />
<item
android:id="@+id/action_layout_colored_card"
android:title="@string/card_color_style" />
<item
android:id="@+id/action_layout_circular"
android:title="@string/circular" />
<item
android:id="@+id/action_layout_image"
android:title="@string/image" />
<item
android:id="@+id/action_layout_gradient_image"
android:title="@string/image_gradient" />
</group>
</menu>
</item>
<item
android:id="@+id/action_sort_order"
android:icon="@drawable/ic_sort"
android:orderInCategory="2"
android:title="@string/action_sort_order"
app:showAsAction="ifRoom">
<menu></menu>
</item>
</menu> </menu>

View file

@ -1,51 +1,47 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android" <navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/retro_graph" xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/action_song"> android:id="@+id/library_graph"
app:startDestination="@id/action_home">
<fragment <fragment
android:id="@+id/action_album" android:id="@+id/action_album"
android:name="code.name.monkey.retromusic.fragments.albums.AlbumsFragment" android:name="code.name.monkey.retromusic.fragments.albums.AlbumsFragment"
android:label="AlbumsFragment" /> tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment <fragment
android:id="@+id/action_artist" android:id="@+id/action_artist"
android:name="code.name.monkey.retromusic.fragments.artists.ArtistsFragment" android:name="code.name.monkey.retromusic.fragments.artists.ArtistsFragment"
android:label="ArtistsFragment" /> tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment <fragment
android:id="@+id/action_song" android:id="@+id/action_song"
android:name="code.name.monkey.retromusic.fragments.songs.SongsFragment" android:name="code.name.monkey.retromusic.fragments.songs.SongsFragment"
android:label="SongsFragment" /> tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment <fragment
android:id="@+id/action_genre" android:id="@+id/action_genre"
android:name="code.name.monkey.retromusic.fragments.genres.GenresFragment" android:name="code.name.monkey.retromusic.fragments.genres.GenresFragment"
android:label="GenresFragment" /> tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment <fragment
android:id="@+id/action_playlist" android:id="@+id/action_playlist"
android:name="code.name.monkey.retromusic.fragments.playlists.PlaylistsFragment" android:name="code.name.monkey.retromusic.fragments.playlists.PlaylistsFragment"
android:label="PlaylistsFragment" /> tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment <fragment
android:id="@+id/action_playing_queue" android:id="@+id/action_playing_queue"
android:name="code.name.monkey.retromusic.fragments.queue.PlayingQueueFragment" android:name="code.name.monkey.retromusic.fragments.queue.PlayingQueueFragment"
android:label="PlayingQueueFragment" /> tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment <fragment
android:id="@+id/action_folder" android:id="@+id/action_folder"
android:name="code.name.monkey.retromusic.fragments.folder.FoldersFragment" android:name="code.name.monkey.retromusic.fragments.folder.FoldersFragment"
android:label="FoldersFragment" /> tools:layout="@layout/fragment_folder" />
<fragment <fragment
android:id="@+id/action_home" android:id="@+id/action_home"
android:name="code.name.monkey.retromusic.fragments.home.BannerHomeFragment" android:name="code.name.monkey.retromusic.fragments.home.HomeFragment"
android:label="BannerHomeFragment" /> tools:layout="@layout/fragment_banner_home" />
<fragment
android:id="@+id/albumDetailsFragment"
android:name="code.name.monkey.retromusic.activities.albums.AlbumDetailsFragment"
android:label="AlbumDetailsFragment" />
</navigation> </navigation>

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/retro_graph"
app:startDestination="@id/libraryFragment">
<include app:graph="@navigation/settings_graph" />
<include app:graph="@navigation/library_graph" />
<fragment
android:id="@+id/genreDetailsFragment"
android:name="code.name.monkey.retromusic.fragments.genres.GenreDetailsFragment"
android:label="GenreDetailsFragment"
tools:layout="@layout/fragment_playlist_detail">
<argument
android:name="extra_genre"
app:argType="code.name.monkey.retromusic.model.Genre" />
</fragment>
<fragment
android:id="@+id/playlistDetailsFragment"
android:name="code.name.monkey.retromusic.fragments.playlists.PlaylistDetailsFragment"
android:label="PlaylistDetailsFragment"
tools:layout="@layout/fragment_playlist_detail">
<argument
android:name="extra_playlist"
app:argType="code.name.monkey.retromusic.model.Playlist" />
</fragment>
<fragment
android:id="@+id/albumDetailsFragment"
android:name="code.name.monkey.retromusic.fragments.albums.AlbumDetailsFragment"
android:label="AlbumDetailsFragment"
tools:layout="@layout/activity_album_details">
<argument
android:name="extra_album_id"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/artistDetailsFragment"
android:name="code.name.monkey.retromusic.fragments.artists.ArtistDetailsFragment"
android:label="ArtistDetailsFragment"
tools:layout="@layout/fragment_artist_details">
<argument
android:name="extra_artist_id"
app:argType="integer" />
</fragment>
<activity
android:id="@+id/action_search"
android:name="code.name.monkey.retromusic.activities.search.SearchActivity"
android:label="Search"
tools:layout="@layout/activity_search" />
<fragment
android:id="@+id/libraryFragment"
android:name="code.name.monkey.retromusic.fragments.library.LibraryFragment"
android:label="LibraryFragment"
tools:layout="@layout/fragment_library">
<action
android:id="@+id/action_main_to_library"
app:destination="@id/library_graph" />
<action
android:id="@+id/action_main_to_settings"
app:destination="@id/settings_graph" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="code.name.monkey.retromusic.activities.search.SearchFragment"
android:label="SearchFragment"
tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/settingsFragment"
android:name="code.name.monkey.retromusic.fragments.settings.SettingsFragment"
android:label="SettingsFragment"
tools:layout="@layout/fragment_settings" />
</navigation>

View file

@ -18,6 +18,7 @@
app:exitAnim="@anim/retro_fragment_open_exit" app:exitAnim="@anim/retro_fragment_open_exit"
app:popEnterAnim="@anim/retro_fragment_close_enter" app:popEnterAnim="@anim/retro_fragment_close_enter"
app:popExitAnim="@anim/retro_fragment_close_exit" /> app:popExitAnim="@anim/retro_fragment_close_exit" />
<action <action
android:id="@+id/action_mainSettingsFragment_to_imageSettingFragment" android:id="@+id/action_mainSettingsFragment_to_imageSettingFragment"
app:destination="@id/imageSettingFragment" app:destination="@id/imageSettingFragment"
@ -25,6 +26,7 @@
app:exitAnim="@anim/retro_fragment_open_exit" app:exitAnim="@anim/retro_fragment_open_exit"
app:popEnterAnim="@anim/retro_fragment_close_enter" app:popEnterAnim="@anim/retro_fragment_close_enter"
app:popExitAnim="@anim/retro_fragment_close_exit" /> app:popExitAnim="@anim/retro_fragment_close_exit" />
<action <action
android:id="@+id/action_mainSettingsFragment_to_nowPlayingSettingsFragment" android:id="@+id/action_mainSettingsFragment_to_nowPlayingSettingsFragment"
app:destination="@id/nowPlayingSettingsFragment" app:destination="@id/nowPlayingSettingsFragment"
@ -32,6 +34,7 @@
app:exitAnim="@anim/retro_fragment_open_exit" app:exitAnim="@anim/retro_fragment_open_exit"
app:popEnterAnim="@anim/retro_fragment_close_enter" app:popEnterAnim="@anim/retro_fragment_close_enter"
app:popExitAnim="@anim/retro_fragment_close_exit" /> app:popExitAnim="@anim/retro_fragment_close_exit" />
<action <action
android:id="@+id/action_mainSettingsFragment_to_audioSettings" android:id="@+id/action_mainSettingsFragment_to_audioSettings"
app:destination="@id/audioSettings" app:destination="@id/audioSettings"
@ -39,6 +42,7 @@
app:exitAnim="@anim/retro_fragment_open_exit" app:exitAnim="@anim/retro_fragment_open_exit"
app:popEnterAnim="@anim/retro_fragment_close_enter" app:popEnterAnim="@anim/retro_fragment_close_enter"
app:popExitAnim="@anim/retro_fragment_close_exit" /> app:popExitAnim="@anim/retro_fragment_close_exit" />
<action <action
android:id="@+id/action_mainSettingsFragment_to_otherSettingsFragment" android:id="@+id/action_mainSettingsFragment_to_otherSettingsFragment"
app:destination="@id/otherSettingsFragment" app:destination="@id/otherSettingsFragment"
@ -46,13 +50,15 @@
app:exitAnim="@anim/retro_fragment_open_exit" app:exitAnim="@anim/retro_fragment_open_exit"
app:popEnterAnim="@anim/retro_fragment_close_enter" app:popEnterAnim="@anim/retro_fragment_close_enter"
app:popExitAnim="@anim/retro_fragment_close_exit" /> app:popExitAnim="@anim/retro_fragment_close_exit" />
<action <action
android:id="@+id/action_mainSettingsFragment_to_personalizeSettingsFragment" android:id="@+id/action_mainSettingsFragment_to_personalizeSettingsFragment"
app:destination="@id/personalizeSettingsFragment"
app:enterAnim="@anim/retro_fragment_open_enter" app:enterAnim="@anim/retro_fragment_open_enter"
app:exitAnim="@anim/retro_fragment_open_exit" app:exitAnim="@anim/retro_fragment_open_exit"
app:popEnterAnim="@anim/retro_fragment_close_enter" app:popEnterAnim="@anim/retro_fragment_close_enter"
app:popExitAnim="@anim/retro_fragment_close_exit" app:popExitAnim="@anim/retro_fragment_close_exit" />
app:destination="@id/personalizeSettingsFragment" />
<action <action
android:id="@+id/action_mainSettingsFragment_to_notificationSettingsFragment" android:id="@+id/action_mainSettingsFragment_to_notificationSettingsFragment"
app:destination="@id/notificationSettingsFragment" app:destination="@id/notificationSettingsFragment"
@ -101,9 +107,9 @@
android:name="code.name.monkey.retromusic.fragments.settings.ThemeSettingsFragment" android:name="code.name.monkey.retromusic.fragments.settings.ThemeSettingsFragment"
android:label="Look &amp; Feel" /> android:label="Look &amp; Feel" />
<activity <fragment
android:id="@+id/aboutActivity" android:id="@+id/aboutActivity"
android:name="code.name.monkey.retromusic.activities.AboutActivity" android:name="code.name.monkey.retromusic.fragments.about.AboutFragment"
android:label="AboutActivity" /> android:label="About" />
</navigation> </navigation>

View file

@ -126,7 +126,7 @@
</string-array> </string-array>
<array name="pref_album_details_style_layout"> <array name="pref_album_details_style_layout">
<item>@layout/activity_album</item> <item>@layout/activity_album_details</item>
</array> </array>
<string-array name="pref_language_names"> <string-array name="pref_language_names">
<item>System default</item> <item>System default</item>

View file

@ -880,4 +880,6 @@
<item quantity="one">%d Artist</item> <item quantity="one">%d Artist</item>
<item quantity="other">%d Artists</item> <item quantity="other">%d Artists</item>
</plurals> </plurals>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources> </resources>