Code refactor
This commit is contained in:
parent
c3153a9650
commit
5a51d0bfc0
50 changed files with 2137 additions and 2105 deletions
|
@ -25,27 +25,21 @@ import code.name.monkey.retromusic.dagger.module.AppModule
|
||||||
import com.anjlab.android.iab.v3.BillingProcessor
|
import com.anjlab.android.iab.v3.BillingProcessor
|
||||||
import com.anjlab.android.iab.v3.TransactionDetails
|
import com.anjlab.android.iab.v3.TransactionDetails
|
||||||
|
|
||||||
|
|
||||||
class App : MultiDexApplication() {
|
class App : MultiDexApplication() {
|
||||||
|
|
||||||
lateinit var billingProcessor: BillingProcessor
|
lateinit var billingProcessor: BillingProcessor
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
/* if (MissingSplitsManagerFactory.create(this).disableAppIfMissingRequiredSplits()) {
|
|
||||||
return
|
|
||||||
}*/
|
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
instance = this
|
instance = this
|
||||||
musicComponent = DaggerMusicComponent.builder()
|
musicComponent = initDagger(this)
|
||||||
.appModule(AppModule(this))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
// default theme
|
// default theme
|
||||||
if (!ThemeStore.isConfigured(this, 3)) {
|
if (!ThemeStore.isConfigured(this, 3)) {
|
||||||
ThemeStore.editTheme(this)
|
ThemeStore.editTheme(this)
|
||||||
.accentColorRes(R.color.md_deep_purple_A200)
|
.accentColorRes(R.color.md_deep_purple_A200)
|
||||||
.coloredNavigationBar(true)
|
.coloredNavigationBar(true)
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VersionUtils.hasNougatMR())
|
if (VersionUtils.hasNougatMR())
|
||||||
|
@ -53,19 +47,25 @@ class App : MultiDexApplication() {
|
||||||
|
|
||||||
// automatically restores purchases
|
// automatically restores purchases
|
||||||
billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY,
|
billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY,
|
||||||
object : BillingProcessor.IBillingHandler {
|
object : BillingProcessor.IBillingHandler {
|
||||||
override fun onProductPurchased(productId: String, details: TransactionDetails?) {}
|
override fun onProductPurchased(productId: String, details: TransactionDetails?) {}
|
||||||
|
|
||||||
override fun onPurchaseHistoryRestored() {
|
override fun onPurchaseHistoryRestored() {
|
||||||
Toast.makeText(this@App, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG).show();
|
Toast.makeText(this@App, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG)
|
||||||
}
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBillingError(errorCode: Int, error: Throwable?) {}
|
override fun onBillingError(errorCode: Int, error: Throwable?) {}
|
||||||
|
|
||||||
override fun onBillingInitialized() {}
|
override fun onBillingInitialized() {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initDagger(app: App): MusicComponent =
|
||||||
|
DaggerMusicComponent.builder()
|
||||||
|
.appModule(AppModule(app))
|
||||||
|
.build()
|
||||||
|
|
||||||
override fun onTerminate() {
|
override fun onTerminate() {
|
||||||
super.onTerminate()
|
super.onTerminate()
|
||||||
billingProcessor.release()
|
billingProcessor.release()
|
||||||
|
@ -85,6 +85,5 @@ class App : MultiDexApplication() {
|
||||||
lateinit var musicComponent: MusicComponent
|
lateinit var musicComponent: MusicComponent
|
||||||
|
|
||||||
const val PRO_VERSION_PRODUCT_ID = "pro_version"
|
const val PRO_VERSION_PRODUCT_ID = "pro_version"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package code.name.monkey.retromusic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sealed class Result<out T : Any> {
|
sealed class Result<out T : Any> {
|
||||||
|
|
||||||
class Success<out T : Any>(val data: T) : Result<T>()
|
class Success<out T : Any>(val data: T) : Result<T>()
|
||||||
|
|
||||||
class Error(val exception: Throwable) : Result<Nothing>()
|
class Error(val exception: Throwable) : Result<Nothing>()
|
||||||
}
|
}
|
|
@ -32,11 +32,22 @@ import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||||
import com.afollestad.materialdialogs.list.listItems
|
import com.afollestad.materialdialogs.list.listItems
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import kotlinx.android.synthetic.main.activity_about.*
|
import kotlinx.android.synthetic.main.activity_about.toolbar
|
||||||
import kotlinx.android.synthetic.main.card_credit.*
|
import kotlinx.android.synthetic.main.card_credit.recyclerView
|
||||||
import kotlinx.android.synthetic.main.card_other.*
|
import kotlinx.android.synthetic.main.card_other.changelog
|
||||||
import kotlinx.android.synthetic.main.card_retro_info.*
|
import kotlinx.android.synthetic.main.card_other.openSource
|
||||||
import kotlinx.android.synthetic.main.card_social.*
|
import kotlinx.android.synthetic.main.card_other.version
|
||||||
|
import kotlinx.android.synthetic.main.card_retro_info.appGithub
|
||||||
|
import kotlinx.android.synthetic.main.card_retro_info.appRate
|
||||||
|
import kotlinx.android.synthetic.main.card_retro_info.appShare
|
||||||
|
import kotlinx.android.synthetic.main.card_retro_info.appTranslation
|
||||||
|
import kotlinx.android.synthetic.main.card_retro_info.bugReportLink
|
||||||
|
import kotlinx.android.synthetic.main.card_retro_info.donateLink
|
||||||
|
import kotlinx.android.synthetic.main.card_retro_info.faqLink
|
||||||
|
import kotlinx.android.synthetic.main.card_social.instagramLink
|
||||||
|
import kotlinx.android.synthetic.main.card_social.pinterestLink
|
||||||
|
import kotlinx.android.synthetic.main.card_social.telegramLink
|
||||||
|
import kotlinx.android.synthetic.main.card_social.twitterLink
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
@ -68,7 +79,6 @@ class AboutActivity : AbsBaseActivity(), View.OnClickListener {
|
||||||
setNavigationbarColorAuto()
|
setNavigationbarColorAuto()
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
|
|
||||||
|
|
||||||
val toolbarColor = ATHUtil.resolveColor(this, R.attr.colorSurface)
|
val toolbarColor = ATHUtil.resolveColor(this, R.attr.colorSurface)
|
||||||
toolbar.setBackgroundColor(toolbarColor)
|
toolbar.setBackgroundColor(toolbarColor)
|
||||||
ToolbarContentTintHelper.colorBackButton(toolbar)
|
ToolbarContentTintHelper.colorBackButton(toolbar)
|
||||||
|
@ -107,7 +117,6 @@ class AboutActivity : AbsBaseActivity(), View.OnClickListener {
|
||||||
openSource.setOnClickListener(this)
|
openSource.setOnClickListener(this)
|
||||||
pinterestLink.setOnClickListener(this)
|
pinterestLink.setOnClickListener(this)
|
||||||
bugReportLink.setOnClickListener(this)
|
bugReportLink.setOnClickListener(this)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(view: View) {
|
override fun onClick(view: View) {
|
||||||
|
@ -153,8 +162,8 @@ class AboutActivity : AbsBaseActivity(), View.OnClickListener {
|
||||||
|
|
||||||
private fun shareApp() {
|
private fun shareApp() {
|
||||||
ShareCompat.IntentBuilder.from(this).setType("text/plain")
|
ShareCompat.IntentBuilder.from(this).setType("text/plain")
|
||||||
.setChooserTitle(R.string.share_app)
|
.setChooserTitle(R.string.share_app)
|
||||||
.setText(String.format(getString(R.string.app_share), packageName)).startChooser()
|
.setText(String.format(getString(R.string.app_share), packageName)).startChooser()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadContributors() {
|
private fun loadContributors() {
|
||||||
|
|
|
@ -42,23 +42,37 @@ import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
import com.afollestad.materialcab.MaterialCab
|
import com.afollestad.materialcab.MaterialCab
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import kotlinx.android.synthetic.main.activity_album.*
|
import kotlinx.android.synthetic.main.activity_album.albumText
|
||||||
import kotlinx.android.synthetic.main.activity_album_content.*
|
import kotlinx.android.synthetic.main.activity_album.albumTitle
|
||||||
import java.util.*
|
import kotlinx.android.synthetic.main.activity_album.image
|
||||||
|
import kotlinx.android.synthetic.main.activity_album.toolbar
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_content.moreRecyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_content.moreTitle
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_content.playAction
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_content.recyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_content.shuffleAction
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_content.songTitle
|
||||||
|
import java.util.ArrayList
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import android.util.Pair as UtilPair
|
import android.util.Pair as UtilPair
|
||||||
|
|
||||||
|
|
||||||
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, CabHolder {
|
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, CabHolder {
|
||||||
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
||||||
cab?.let {
|
cab?.let {
|
||||||
if (it.isActive) it.finish()
|
if (it.isActive) it.finish()
|
||||||
}
|
}
|
||||||
cab = MaterialCab(this, R.id.cab_stub)
|
cab = MaterialCab(this, R.id.cab_stub)
|
||||||
.setMenu(menuRes)
|
.setMenu(menuRes)
|
||||||
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||||
.setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ATHUtil.resolveColor(this, R.attr.colorSurface)))
|
.setBackgroundColor(
|
||||||
.start(callback)
|
RetroColorUtil.shiftBackgroundColorForLightText(
|
||||||
|
ATHUtil.resolveColor(
|
||||||
|
this,
|
||||||
|
R.attr.colorSurface
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.start(callback)
|
||||||
return cab as MaterialCab
|
return cab as MaterialCab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +107,10 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
|
|
||||||
artistImage.setOnClickListener {
|
artistImage.setOnClickListener {
|
||||||
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(this, UtilPair.create(artistImage, getString(R.string.transition_artist_image)))
|
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(
|
||||||
|
this,
|
||||||
|
UtilPair.create(artistImage, getString(R.string.transition_artist_image))
|
||||||
|
)
|
||||||
NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
|
NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
|
||||||
}
|
}
|
||||||
playAction.apply {
|
playAction.apply {
|
||||||
|
@ -142,9 +159,18 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
|
|
||||||
albumTitle.text = album.title
|
albumTitle.text = album.title
|
||||||
if (MusicUtil.getYearString(album.year) == "-") {
|
if (MusicUtil.getYearString(album.year) == "-") {
|
||||||
albumText.text = String.format("%s • %s", album.artistName, MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, album.songs)))
|
albumText.text = String.format(
|
||||||
|
"%s • %s",
|
||||||
|
album.artistName,
|
||||||
|
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, album.songs))
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
albumText.text = String.format("%s • %s • %s", album.artistName, MusicUtil.getYearString(album.year), MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, album.songs)))
|
albumText.text = String.format(
|
||||||
|
"%s • %s • %s",
|
||||||
|
album.artistName,
|
||||||
|
MusicUtil.getYearString(album.year),
|
||||||
|
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, album.songs))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
loadAlbumCover()
|
loadAlbumCover()
|
||||||
simpleSongAdapter.swapDataSet(album.songs)
|
simpleSongAdapter.swapDataSet(album.songs)
|
||||||
|
@ -158,22 +184,20 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
|
|
||||||
val albumAdapter = HorizontalAlbumAdapter(this, albums, false, null)
|
val albumAdapter = HorizontalAlbumAdapter(this, albums, false, null)
|
||||||
moreRecyclerView.layoutManager = GridLayoutManager(
|
moreRecyclerView.layoutManager = GridLayoutManager(
|
||||||
this,
|
this,
|
||||||
1,
|
1,
|
||||||
GridLayoutManager.HORIZONTAL,
|
GridLayoutManager.HORIZONTAL,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
moreRecyclerView.adapter = albumAdapter
|
moreRecyclerView.adapter = albumAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadArtistImage(artist: Artist) {
|
override fun loadArtistImage(artist: Artist) {
|
||||||
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
||||||
.dontAnimate().dontTransform().into(object : RetroMusicColoredTarget(artistImage) {
|
.dontAnimate().dontTransform().into(object : RetroMusicColoredTarget(artistImage) {
|
||||||
override fun onColorReady(color: Int) {
|
override fun onColorReady(color: Int) {
|
||||||
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAlbumCover() {
|
private fun loadAlbumCover() {
|
||||||
|
@ -183,15 +207,15 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
.dontAnimate().into(image)*/
|
.dontAnimate().into(image)*/
|
||||||
|
|
||||||
SongGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong())
|
SongGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong())
|
||||||
.checkIgnoreMediaStore(this)
|
.checkIgnoreMediaStore(this)
|
||||||
.ignoreMediaStore(PreferenceUtil.getInstance(this).ignoreMediaStoreArtwork())
|
.ignoreMediaStore(PreferenceUtil.getInstance(this).ignoreMediaStoreArtwork())
|
||||||
.generatePalette(this)
|
.generatePalette(this)
|
||||||
.build().dontAnimate().dontTransform()
|
.build().dontAnimate().dontTransform()
|
||||||
.into(object : RetroMusicColoredTarget(image) {
|
.into(object : RetroMusicColoredTarget(image) {
|
||||||
override fun onColorReady(color: Int) {
|
override fun onColorReady(color: Int) {
|
||||||
setColors(color)
|
setColors(color)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColors(color: Int) {
|
private fun setColors(color: Int) {
|
||||||
|
@ -254,7 +278,11 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
R.id.action_tag_editor -> {
|
R.id.action_tag_editor -> {
|
||||||
val intent = Intent(this, AlbumTagEditorActivity::class.java)
|
val intent = Intent(this, AlbumTagEditorActivity::class.java)
|
||||||
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.id)
|
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.id)
|
||||||
val options = ActivityOptions.makeSceneTransitionAnimation(this, image, getString(R.string.transition_album_art))
|
val options = ActivityOptions.makeSceneTransitionAnimation(
|
||||||
|
this,
|
||||||
|
image,
|
||||||
|
getString(R.string.transition_album_art)
|
||||||
|
)
|
||||||
startActivityForResult(intent, TAG_EDITOR_REQUEST, options.toBundle())
|
startActivityForResult(intent, TAG_EDITOR_REQUEST, options.toBundle())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -275,8 +303,10 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
when (savedSortOrder) {
|
when (savedSortOrder) {
|
||||||
AlbumSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title).isChecked = true
|
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_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_TRACK_LIST -> sortOrder.findItem(R.id.action_sort_order_track_list).isChecked =
|
||||||
AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration).isChecked = true
|
true
|
||||||
|
AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration)
|
||||||
|
.isChecked = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,14 +33,29 @@ import code.name.monkey.retromusic.model.Artist
|
||||||
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter
|
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter
|
||||||
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView
|
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView
|
||||||
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
||||||
import code.name.monkey.retromusic.util.*
|
import code.name.monkey.retromusic.util.CustomArtistImageUtil
|
||||||
|
import code.name.monkey.retromusic.util.DensityUtil
|
||||||
|
import code.name.monkey.retromusic.util.MusicUtil
|
||||||
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import com.afollestad.materialcab.MaterialCab
|
import com.afollestad.materialcab.MaterialCab
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import kotlinx.android.synthetic.main.activity_artist_content.*
|
import kotlinx.android.synthetic.main.activity_artist_content.albumRecyclerView
|
||||||
import kotlinx.android.synthetic.main.activity_artist_details.*
|
import kotlinx.android.synthetic.main.activity_artist_content.albumTitle
|
||||||
import java.util.*
|
import kotlinx.android.synthetic.main.activity_artist_content.biographyText
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_content.biographyTitle
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_content.playAction
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_content.recyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_content.shuffleAction
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_content.songTitle
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_details.artistImage
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_details.artistTitle
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_details.imageContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_details.text
|
||||||
|
import kotlinx.android.synthetic.main.activity_artist_details.toolbar
|
||||||
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, CabHolder {
|
class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, CabHolder {
|
||||||
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
||||||
|
@ -48,10 +63,17 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
if (it.isActive) it.finish()
|
if (it.isActive) it.finish()
|
||||||
}
|
}
|
||||||
cab = MaterialCab(this, R.id.cab_stub)
|
cab = MaterialCab(this, R.id.cab_stub)
|
||||||
.setMenu(menuRes)
|
.setMenu(menuRes)
|
||||||
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||||
.setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ATHUtil.resolveColor(this, R.attr.colorSurface)))
|
.setBackgroundColor(
|
||||||
.start(callback)
|
RetroColorUtil.shiftBackgroundColorForLightText(
|
||||||
|
ATHUtil.resolveColor(
|
||||||
|
this,
|
||||||
|
R.attr.colorSurface
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.start(callback)
|
||||||
return cab as MaterialCab
|
return cab as MaterialCab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +177,6 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmptyView() {
|
override fun showEmptyView() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun complete() {
|
override fun complete() {
|
||||||
|
@ -174,9 +195,9 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
}
|
}
|
||||||
artistTitle.text = artist.name
|
artistTitle.text = artist.name
|
||||||
text.text = String.format(
|
text.text = String.format(
|
||||||
"%s • %s",
|
"%s • %s",
|
||||||
MusicUtil.getArtistInfoString(this, artist),
|
MusicUtil.getArtistInfoString(this, artist),
|
||||||
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, artist.songs))
|
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, artist.songs))
|
||||||
)
|
)
|
||||||
|
|
||||||
songAdapter.swapDataSet(artist.songs)
|
songAdapter.swapDataSet(artist.songs)
|
||||||
|
@ -184,8 +205,8 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadBiography(
|
private fun loadBiography(
|
||||||
name: String,
|
name: String,
|
||||||
lang: String? = Locale.getDefault().language
|
lang: String? = Locale.getDefault().language
|
||||||
) {
|
) {
|
||||||
biography = null
|
biography = null
|
||||||
this.lang = lang
|
this.lang = lang
|
||||||
|
@ -217,11 +238,11 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
|
|
||||||
private fun loadArtistImage() {
|
private fun loadArtistImage() {
|
||||||
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
||||||
.dontAnimate().into(object : RetroMusicColoredTarget(artistImage) {
|
.dontAnimate().into(object : RetroMusicColoredTarget(artistImage) {
|
||||||
override fun onColorReady(color: Int) {
|
override fun onColorReady(color: Int) {
|
||||||
setColors(color)
|
setColors(color)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColors(color: Int) {
|
private fun setColors(color: Int) {
|
||||||
|
@ -275,11 +296,15 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
R.id.action_set_artist_image -> {
|
R.id.action_set_artist_image -> {
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||||
intent.type = "image/*"
|
intent.type = "image/*"
|
||||||
startActivityForResult(Intent.createChooser(intent, getString(R.string.pick_from_local_storage)), REQUEST_CODE_SELECT_IMAGE)
|
startActivityForResult(
|
||||||
|
Intent.createChooser(intent, getString(R.string.pick_from_local_storage)),
|
||||||
|
REQUEST_CODE_SELECT_IMAGE
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.action_reset_artist_image -> {
|
R.id.action_reset_artist_image -> {
|
||||||
Toast.makeText(this@ArtistDetailActivity, resources.getString(R.string.updating), Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@ArtistDetailActivity, resources.getString(R.string.updating), Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
CustomArtistImageUtil.getInstance(this@ArtistDetailActivity).resetCustomArtistImage(artist)
|
CustomArtistImageUtil.getInstance(this@ArtistDetailActivity).resetCustomArtistImage(artist)
|
||||||
forceDownload = true
|
forceDownload = true
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -23,8 +23,11 @@ import code.name.monkey.retromusic.util.DensityUtil
|
||||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
import code.name.monkey.retromusic.util.ViewUtil
|
import code.name.monkey.retromusic.util.ViewUtil
|
||||||
import com.afollestad.materialcab.MaterialCab
|
import com.afollestad.materialcab.MaterialCab
|
||||||
import kotlinx.android.synthetic.main.activity_playlist_detail.*
|
import kotlinx.android.synthetic.main.activity_playlist_detail.empty
|
||||||
import java.util.*
|
import kotlinx.android.synthetic.main.activity_playlist_detail.emptyEmoji
|
||||||
|
import kotlinx.android.synthetic.main.activity_playlist_detail.recyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_playlist_detail.toolbar
|
||||||
|
import java.util.ArrayList
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,7 +78,6 @@ class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDet
|
||||||
|
|
||||||
App.musicComponent.inject(this)
|
App.musicComponent.inject(this)
|
||||||
genreDetailsPresenter.attachView(this)
|
genreDetailsPresenter.attachView(this)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpToolBar() {
|
private fun setUpToolBar() {
|
||||||
|
@ -98,7 +100,6 @@ class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDet
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmptyView() {
|
override fun showEmptyView() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
@ -135,7 +136,15 @@ class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDet
|
||||||
|
|
||||||
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
||||||
if (cab != null && cab!!.isActive) cab?.finish()
|
if (cab != null && cab!!.isActive) cab?.finish()
|
||||||
cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes).setCloseDrawableRes(R.drawable.ic_close_white_24dp).setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ATHUtil.resolveColor(this, R.attr.colorSurface))).start(callback)
|
cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes).setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||||
|
.setBackgroundColor(
|
||||||
|
RetroColorUtil.shiftBackgroundColorForLightText(
|
||||||
|
ATHUtil.resolveColor(
|
||||||
|
this,
|
||||||
|
R.attr.colorSurface
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).start(callback)
|
||||||
return cab!!
|
return cab!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,47 +14,30 @@
|
||||||
|
|
||||||
package code.name.monkey.retromusic.activities;
|
package code.name.monkey.retromusic.activities;
|
||||||
|
|
||||||
|
import static code.name.monkey.appthemehelper.util.ATHUtil.INSTANCE;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import code.name.monkey.appthemehelper.ThemeStore;
|
import code.name.monkey.appthemehelper.ThemeStore;
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil;
|
import code.name.monkey.appthemehelper.util.ColorUtil;
|
||||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
|
||||||
import code.name.monkey.retromusic.R;
|
import code.name.monkey.retromusic.R;
|
||||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity;
|
import code.name.monkey.retromusic.activities.base.AbsBaseActivity;
|
||||||
|
import java.io.BufferedReader;
|
||||||
import static code.name.monkey.appthemehelper.util.ATHUtil.INSTANCE;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hemanths on 2019-09-27.
|
* Created by hemanths on 2019-09-27.
|
||||||
*/
|
*/
|
||||||
public class LicenseActivity extends AbsBaseActivity {
|
public class LicenseActivity extends AbsBaseActivity {
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
onBackPressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String colorToCSS(int color) {
|
|
||||||
return String.format("rgb(%d, %d, %d)", Color.red(color), Color.green(color), Color.blue(color)); // on API 29, WebView doesn't load with hex colors
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
setDrawUnderStatusBar();
|
setDrawUnderStatusBar();
|
||||||
|
@ -73,19 +56,22 @@ public class LicenseActivity extends AbsBaseActivity {
|
||||||
InputStream json = getAssets().open("index.html");
|
InputStream json = getAssets().open("index.html");
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(json, StandardCharsets.UTF_8));
|
BufferedReader in = new BufferedReader(new InputStreamReader(json, StandardCharsets.UTF_8));
|
||||||
String str;
|
String str;
|
||||||
while ((str = in.readLine()) != null)
|
while ((str = in.readLine()) != null) {
|
||||||
buf.append(str);
|
buf.append(str);
|
||||||
|
}
|
||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
// Inject color values for WebView body background and links
|
// Inject color values for WebView body background and links
|
||||||
final boolean isDark = INSTANCE.isWindowBackgroundDark(this);
|
final boolean isDark = INSTANCE.isWindowBackgroundDark(this);
|
||||||
final String backgroundColor = colorToCSS(INSTANCE.resolveColor(this, R.attr.colorSurface, Color.parseColor(isDark ? "#424242" : "#ffffff")));
|
final String backgroundColor = colorToCSS(INSTANCE.resolveColor(this, R.attr.colorSurface,
|
||||||
|
Color.parseColor(isDark ? "#424242" : "#ffffff")));
|
||||||
final String contentColor = colorToCSS(Color.parseColor(isDark ? "#ffffff" : "#000000"));
|
final String contentColor = colorToCSS(Color.parseColor(isDark ? "#ffffff" : "#000000"));
|
||||||
final String changeLog = buf.toString()
|
final String changeLog = buf.toString()
|
||||||
.replace("{style-placeholder}",
|
.replace("{style-placeholder}",
|
||||||
String.format("body { background-color: %s; color: %s; }", backgroundColor, contentColor))
|
String.format("body { background-color: %s; color: %s; }", backgroundColor, contentColor))
|
||||||
.replace("{link-color}", colorToCSS(ThemeStore.Companion.accentColor(this)))
|
.replace("{link-color}", colorToCSS(ThemeStore.Companion.accentColor(this)))
|
||||||
.replace("{link-color-active}", colorToCSS(ColorUtil.INSTANCE.lightenColor(ThemeStore.Companion.accentColor(this))));
|
.replace("{link-color-active}",
|
||||||
|
colorToCSS(ColorUtil.INSTANCE.lightenColor(ThemeStore.Companion.accentColor(this))));
|
||||||
|
|
||||||
webView.loadData(changeLog, "text/html", "UTF-8");
|
webView.loadData(changeLog, "text/html", "UTF-8");
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -93,4 +79,18 @@ public class LicenseActivity extends AbsBaseActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||||
|
if (item.getItemId() == android.R.id.home) {
|
||||||
|
onBackPressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String colorToCSS(int color) {
|
||||||
|
return String.format("rgb(%d, %d, %d)", Color.red(color), Color.green(color),
|
||||||
|
Color.blue(color)); // on API 29, WebView doesn't load with hex colors
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,79 +18,79 @@ import com.r0adkll.slidr.Slidr
|
||||||
import com.r0adkll.slidr.model.SlidrConfig
|
import com.r0adkll.slidr.model.SlidrConfig
|
||||||
import com.r0adkll.slidr.model.SlidrListener
|
import com.r0adkll.slidr.model.SlidrListener
|
||||||
import com.r0adkll.slidr.model.SlidrPosition
|
import com.r0adkll.slidr.model.SlidrPosition
|
||||||
import kotlinx.android.synthetic.main.activity_lock_screen.*
|
import kotlinx.android.synthetic.main.activity_lock_screen.image
|
||||||
|
|
||||||
class LockScreenActivity : AbsMusicServiceActivity() {
|
class LockScreenActivity : AbsMusicServiceActivity() {
|
||||||
private var fragment: LockScreenPlayerControlsFragment? = null
|
private var fragment: LockScreenPlayerControlsFragment? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||||
setShowWhenLocked(true)
|
setShowWhenLocked(true)
|
||||||
setTurnScreenOn(true)
|
setTurnScreenOn(true)
|
||||||
} else {
|
} else {
|
||||||
this.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
this.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
|
||||||
}
|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
||||||
setDrawUnderStatusBar()
|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
||||||
setContentView(R.layout.activity_lock_screen)
|
}
|
||||||
hideStatusBar()
|
setDrawUnderStatusBar()
|
||||||
setStatusbarColorAuto()
|
setContentView(R.layout.activity_lock_screen)
|
||||||
setNavigationbarColorAuto()
|
hideStatusBar()
|
||||||
setTaskDescriptionColorAuto()
|
setStatusbarColorAuto()
|
||||||
setLightNavigationBar(true)
|
setNavigationbarColorAuto()
|
||||||
|
setTaskDescriptionColorAuto()
|
||||||
|
setLightNavigationBar(true)
|
||||||
|
|
||||||
val config = SlidrConfig.Builder().listener(object : SlidrListener {
|
val config = SlidrConfig.Builder().listener(object : SlidrListener {
|
||||||
override fun onSlideStateChanged(state: Int) {
|
override fun onSlideStateChanged(state: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
override fun onSlideChange(percent: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onSlideChange(percent: Float) {
|
override fun onSlideOpened() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
override fun onSlideClosed(): Boolean {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
||||||
|
keyguardManager.requestDismissKeyguard(this@LockScreenActivity, null)
|
||||||
|
}
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}).position(SlidrPosition.BOTTOM).build()
|
||||||
|
|
||||||
override fun onSlideOpened() {
|
Slidr.attach(this, config)
|
||||||
|
|
||||||
}
|
fragment =
|
||||||
|
supportFragmentManager.findFragmentById(R.id.playback_controls_fragment) as LockScreenPlayerControlsFragment?
|
||||||
|
|
||||||
override fun onSlideClosed(): Boolean {
|
findViewById<View>(R.id.slide).apply {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
translationY = 100f
|
||||||
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
alpha = 0f
|
||||||
keyguardManager.requestDismissKeyguard(this@LockScreenActivity, null)
|
ViewCompat.animate(this).translationY(0f).alpha(1f).setDuration(1500).start()
|
||||||
}
|
}
|
||||||
finish()
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
}).position(SlidrPosition.BOTTOM).build()
|
|
||||||
|
|
||||||
Slidr.attach(this, config)
|
override fun onPlayingMetaChanged() {
|
||||||
|
super.onPlayingMetaChanged()
|
||||||
|
updateSongs()
|
||||||
|
}
|
||||||
|
|
||||||
fragment = supportFragmentManager.findFragmentById(R.id.playback_controls_fragment) as LockScreenPlayerControlsFragment?
|
override fun onServiceConnected() {
|
||||||
|
super.onServiceConnected()
|
||||||
|
updateSongs()
|
||||||
|
}
|
||||||
|
|
||||||
findViewById<View>(R.id.slide).apply {
|
private fun updateSongs() {
|
||||||
translationY = 100f
|
val song = MusicPlayerRemote.currentSong
|
||||||
alpha = 0f
|
SongGlideRequest.Builder.from(Glide.with(this), song).checkIgnoreMediaStore(this)
|
||||||
ViewCompat.animate(this).translationY(0f).alpha(1f).setDuration(1500).start()
|
.generatePalette(this).build().dontAnimate()
|
||||||
}
|
.into(object : RetroMusicColoredTarget(image) {
|
||||||
}
|
override fun onColorReady(color: Int) {
|
||||||
|
fragment?.setDark(color)
|
||||||
override fun onPlayingMetaChanged() {
|
}
|
||||||
super.onPlayingMetaChanged()
|
})
|
||||||
updateSongs()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
|
||||||
super.onServiceConnected()
|
|
||||||
updateSongs()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateSongs() {
|
|
||||||
val song = MusicPlayerRemote.currentSong
|
|
||||||
SongGlideRequest.Builder.from(Glide.with(this), song).checkIgnoreMediaStore(this)
|
|
||||||
.generatePalette(this).build().dontAnimate()
|
|
||||||
.into(object : RetroMusicColoredTarget(image) {
|
|
||||||
override fun onColorReady(color: Int) {
|
|
||||||
fragment?.setDark(color)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -7,7 +7,11 @@ import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowManager
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
@ -15,7 +19,12 @@ import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.*
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
|
import code.name.monkey.appthemehelper.util.MaterialUtil
|
||||||
|
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
|
import code.name.monkey.appthemehelper.util.TintHelper
|
||||||
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.App
|
import code.name.monkey.retromusic.App
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||||
|
@ -36,13 +45,15 @@ import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||||
import com.afollestad.materialdialogs.input.getInputLayout
|
import com.afollestad.materialdialogs.input.getInputLayout
|
||||||
import com.afollestad.materialdialogs.input.input
|
import com.afollestad.materialdialogs.input.input
|
||||||
import kotlinx.android.synthetic.main.activity_lyrics.*
|
import kotlinx.android.synthetic.main.activity_lyrics.fab
|
||||||
import kotlinx.android.synthetic.main.fragment_lyrics.*
|
import kotlinx.android.synthetic.main.activity_lyrics.tabs
|
||||||
import kotlinx.android.synthetic.main.fragment_synced.*
|
import kotlinx.android.synthetic.main.activity_lyrics.toolbar
|
||||||
|
import kotlinx.android.synthetic.main.activity_lyrics.viewPager
|
||||||
|
import kotlinx.android.synthetic.main.fragment_lyrics.offlineLyrics
|
||||||
|
import kotlinx.android.synthetic.main.fragment_synced.lyricsView
|
||||||
import org.jaudiotagger.tag.FieldKey
|
import org.jaudiotagger.tag.FieldKey
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.EnumMap
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPager.OnPageChangeListener {
|
class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPager.OnPageChangeListener {
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
|
@ -89,11 +100,16 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
setNavigationbarColorAuto()
|
setNavigationbarColorAuto()
|
||||||
|
|
||||||
fab.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
fab.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
||||||
ColorStateList.valueOf(MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(ThemeStore.accentColor(this))))
|
ColorStateList.valueOf(
|
||||||
.apply {
|
MaterialValueHelper.getPrimaryTextColor(
|
||||||
fab.setTextColor(this)
|
this,
|
||||||
fab.iconTint = this
|
ColorUtil.isColorLight(ThemeStore.accentColor(this))
|
||||||
}
|
)
|
||||||
|
)
|
||||||
|
.apply {
|
||||||
|
fab.setTextColor(this)
|
||||||
|
fab.iconTint = this
|
||||||
|
}
|
||||||
setupWakelock()
|
setupWakelock()
|
||||||
|
|
||||||
viewPager.apply {
|
viewPager.apply {
|
||||||
|
@ -108,8 +124,18 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
ToolbarContentTintHelper.colorBackButton(toolbar)
|
ToolbarContentTintHelper.colorBackButton(toolbar)
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
tabs.setupWithViewPager(viewPager)
|
tabs.setupWithViewPager(viewPager)
|
||||||
tabs.setSelectedTabIndicator(TintHelper.createTintedDrawable(ContextCompat.getDrawable(this, R.drawable.tab_indicator), ThemeStore.accentColor(this)))
|
tabs.setSelectedTabIndicator(
|
||||||
tabs.setTabTextColors(ATHUtil.resolveColor(this, android.R.attr.textColorSecondary), ThemeStore.accentColor(this))
|
TintHelper.createTintedDrawable(
|
||||||
|
ContextCompat.getDrawable(
|
||||||
|
this,
|
||||||
|
R.drawable.tab_indicator
|
||||||
|
), ThemeStore.accentColor(this)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
tabs.setTabTextColors(
|
||||||
|
ATHUtil.resolveColor(this, android.R.attr.textColorSecondary),
|
||||||
|
ThemeStore.accentColor(this)
|
||||||
|
)
|
||||||
tabs.setSelectedTabIndicatorColor(ThemeStore.accentColor(this))
|
tabs.setSelectedTabIndicatorColor(ThemeStore.accentColor(this))
|
||||||
|
|
||||||
fab.setOnClickListener(this)
|
fab.setOnClickListener(this)
|
||||||
|
@ -152,29 +178,30 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
}
|
}
|
||||||
|
|
||||||
val materialDialog = MaterialDialog(this, BottomSheet(LayoutMode.WRAP_CONTENT))
|
val materialDialog = MaterialDialog(this, BottomSheet(LayoutMode.WRAP_CONTENT))
|
||||||
.show {
|
.show {
|
||||||
cornerRadius(PreferenceUtil.getInstance(this@LyricsActivity).dialogCorner)
|
cornerRadius(PreferenceUtil.getInstance(this@LyricsActivity).dialogCorner)
|
||||||
title(R.string.add_time_framed_lryics)
|
title(R.string.add_time_framed_lryics)
|
||||||
negativeButton(R.string.action_search) {
|
negativeButton(R.string.action_search) {
|
||||||
RetroUtil.openUrl(this@LyricsActivity, googleSearchLrcUrl)
|
RetroUtil.openUrl(this@LyricsActivity, googleSearchLrcUrl)
|
||||||
}
|
|
||||||
input(
|
|
||||||
hint = getString(R.string.paste_lyrics_here),
|
|
||||||
prefill = content,
|
|
||||||
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
|
|
||||||
) { _, input ->
|
|
||||||
LyricUtil.writeLrcToLoc(song.title, song.artistName, input.toString())
|
|
||||||
}
|
|
||||||
positiveButton(android.R.string.ok) {
|
|
||||||
updateSong()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
input(
|
||||||
|
hint = getString(R.string.paste_lyrics_here),
|
||||||
|
prefill = content,
|
||||||
|
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
|
||||||
|
) { _, input ->
|
||||||
|
LyricUtil.writeLrcToLoc(song.title, song.artistName, input.toString())
|
||||||
|
}
|
||||||
|
positiveButton(android.R.string.ok) {
|
||||||
|
updateSong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MaterialUtil.setTint(materialDialog.getInputLayout(), false)
|
MaterialUtil.setTint(materialDialog.getInputLayout(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSong() {
|
private fun updateSong() {
|
||||||
val page = supportFragmentManager.findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager.currentItem)
|
val page =
|
||||||
|
supportFragmentManager.findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager.currentItem)
|
||||||
if (viewPager.currentItem == 0 && page != null) {
|
if (viewPager.currentItem == 0 && page != null) {
|
||||||
(page as BaseLyricsFragment).upDateSong()
|
(page as BaseLyricsFragment).upDateSong()
|
||||||
}
|
}
|
||||||
|
@ -188,7 +215,7 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
}
|
}
|
||||||
|
|
||||||
val materialDialog = MaterialDialog(
|
val materialDialog = MaterialDialog(
|
||||||
this, BottomSheet(LayoutMode.WRAP_CONTENT)
|
this, BottomSheet(LayoutMode.WRAP_CONTENT)
|
||||||
).show {
|
).show {
|
||||||
cornerRadius(PreferenceUtil.getInstance(this@LyricsActivity).dialogCorner)
|
cornerRadius(PreferenceUtil.getInstance(this@LyricsActivity).dialogCorner)
|
||||||
title(R.string.add_lyrics)
|
title(R.string.add_lyrics)
|
||||||
|
@ -196,16 +223,16 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
RetroUtil.openUrl(this@LyricsActivity, getGoogleSearchUrl())
|
RetroUtil.openUrl(this@LyricsActivity, getGoogleSearchUrl())
|
||||||
}
|
}
|
||||||
input(
|
input(
|
||||||
hint = getString(R.string.paste_lyrics_here),
|
hint = getString(R.string.paste_lyrics_here),
|
||||||
prefill = content,
|
prefill = content,
|
||||||
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
|
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
|
||||||
) { _, input ->
|
) { _, input ->
|
||||||
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
||||||
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
|
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
|
||||||
WriteTagsAsyncTask(this@LyricsActivity).execute(
|
WriteTagsAsyncTask(this@LyricsActivity).execute(
|
||||||
WriteTagsAsyncTask.LoadingInfo(
|
WriteTagsAsyncTask.LoadingInfo(
|
||||||
getSongPaths(song), fieldKeyValueMap, null
|
getSongPaths(song), fieldKeyValueMap, null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
positiveButton(android.R.string.ok) {
|
positiveButton(android.R.string.ok) {
|
||||||
|
@ -230,10 +257,11 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
}
|
}
|
||||||
|
|
||||||
class PagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(
|
class PagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(
|
||||||
fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
|
fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
|
||||||
) {
|
) {
|
||||||
|
|
||||||
class Tabs(
|
class Tabs(
|
||||||
@StringRes val title: Int, val fragment: Fragment
|
@StringRes val title: Int, val fragment: Fragment
|
||||||
)
|
)
|
||||||
|
|
||||||
private var tabs = ArrayList<Tabs>()
|
private var tabs = ArrayList<Tabs>()
|
||||||
|
@ -256,7 +284,6 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
override fun getCount(): Int {
|
override fun getCount(): Int {
|
||||||
return tabs.size
|
return tabs.size
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class BaseLyricsFragment : AbsMusicServiceFragment() {
|
abstract class BaseLyricsFragment : AbsMusicServiceFragment() {
|
||||||
|
@ -271,7 +298,6 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
super.onServiceConnected()
|
super.onServiceConnected()
|
||||||
upDateSong()
|
upDateSong()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OfflineLyricsFragment : BaseLyricsFragment() {
|
class OfflineLyricsFragment : BaseLyricsFragment() {
|
||||||
|
@ -331,7 +357,7 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
return inflater.inflate(R.layout.fragment_lyrics, container, false)
|
return inflater.inflate(R.layout.fragment_lyrics, container, false)
|
||||||
}
|
}
|
||||||
|
@ -344,7 +370,7 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPage
|
||||||
|
|
||||||
private lateinit var updateHelper: MusicProgressViewUpdateHelper
|
private lateinit var updateHelper: MusicProgressViewUpdateHelper
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
return inflater.inflate(R.layout.fragment_synced, container, false)
|
return inflater.inflate(R.layout.fragment_synced, container, false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package code.name.monkey.retromusic.activities
|
package code.name.monkey.retromusic.activities
|
||||||
|
|
||||||
import android.content.*
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
@ -22,7 +26,7 @@ import code.name.monkey.retromusic.service.MusicService
|
||||||
import code.name.monkey.retromusic.util.AppRater
|
import code.name.monkey.retromusic.util.AppRater
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
|
|
||||||
class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
|
class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
@ -49,7 +53,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(
|
override fun onCreate(
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
) {
|
) {
|
||||||
setDrawUnderStatusBar()
|
setDrawUnderStatusBar()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -76,14 +80,13 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
||||||
val currentVersion = pInfo.versionCode
|
val currentVersion = pInfo.versionCode
|
||||||
if (currentVersion != PreferenceUtil.getInstance(this).lastChangelogVersion) {
|
if (currentVersion != PreferenceUtil.getInstance(this).lastChangelogVersion) {
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
Intent(this, WhatsNewActivity::class.java),
|
Intent(this, WhatsNewActivity::class.java),
|
||||||
APP_INTRO_REQUEST
|
APP_INTRO_REQUEST
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -112,13 +115,14 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
||||||
private fun setCurrentFragment(fragment: Fragment, tag: String) {
|
private fun setCurrentFragment(fragment: Fragment, tag: String) {
|
||||||
if (tag != supportFragmentManager.findFragmentById(R.id.fragment_container)?.tag) {
|
if (tag != supportFragmentManager.findFragmentById(R.id.fragment_container)?.tag) {
|
||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.beginTransaction()
|
||||||
.replace(R.id.fragment_container, fragment, tag).commit()
|
.replace(R.id.fragment_container, fragment, tag).commit()
|
||||||
currentFragment = fragment as MainActivityFragmentCallbacks
|
currentFragment = fragment as MainActivityFragmentCallbacks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreCurrentFragment() {
|
private fun restoreCurrentFragment() {
|
||||||
currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as MainActivityFragmentCallbacks
|
currentFragment =
|
||||||
|
supportFragmentManager.findFragmentById(R.id.fragment_container) as MainActivityFragmentCallbacks
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handlePlaybackIntent(intent: Intent?) {
|
private fun handlePlaybackIntent(intent: Intent?) {
|
||||||
|
@ -200,7 +204,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleBackPress(): Boolean {
|
override fun handleBackPress(): Boolean {
|
||||||
|
@ -219,8 +222,8 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||||
if (key == PreferenceUtil.GENERAL_THEME || key == PreferenceUtil.BLACK_THEME || key == PreferenceUtil.ADAPTIVE_COLOR_APP || key == PreferenceUtil.DOMINANT_COLOR || key == PreferenceUtil.USER_NAME || key == PreferenceUtil.TOGGLE_FULL_SCREEN || key == PreferenceUtil.TOGGLE_VOLUME || key == PreferenceUtil.ROUND_CORNERS || key == PreferenceUtil.CAROUSEL_EFFECT || key == PreferenceUtil.NOW_PLAYING_SCREEN_ID || key == PreferenceUtil.TOGGLE_GENRE || key == PreferenceUtil.BANNER_IMAGE_PATH || key == PreferenceUtil.PROFILE_IMAGE_PATH || key == PreferenceUtil.CIRCULAR_ALBUM_ART || key == PreferenceUtil.KEEP_SCREEN_ON || key == PreferenceUtil.TOGGLE_SEPARATE_LINE || key == PreferenceUtil.ALBUM_GRID_STYLE || key == PreferenceUtil.ARTIST_GRID_STYLE || key == PreferenceUtil.TOGGLE_HOME_BANNER || key == PreferenceUtil.TOGGLE_ADD_CONTROLS || key == PreferenceUtil.ALBUM_COVER_STYLE || key == PreferenceUtil.HOME_ARTIST_GRID_STYLE || key == PreferenceUtil.ALBUM_COVER_TRANSFORM || key == PreferenceUtil.DESATURATED_COLOR || key == PreferenceUtil.TAB_TEXT_MODE || key == PreferenceUtil.LIBRARY_CATEGORIES) postRecreate()
|
if (key == PreferenceUtil.GENERAL_THEME || key == PreferenceUtil.BLACK_THEME || key == PreferenceUtil.ADAPTIVE_COLOR_APP || key == PreferenceUtil.DOMINANT_COLOR || key == PreferenceUtil.USER_NAME || key == PreferenceUtil.TOGGLE_FULL_SCREEN || key == PreferenceUtil.TOGGLE_VOLUME || key == PreferenceUtil.ROUND_CORNERS || key == PreferenceUtil.CAROUSEL_EFFECT || key == PreferenceUtil.NOW_PLAYING_SCREEN_ID || key == PreferenceUtil.TOGGLE_GENRE || key == PreferenceUtil.BANNER_IMAGE_PATH || key == PreferenceUtil.PROFILE_IMAGE_PATH || key == PreferenceUtil.CIRCULAR_ALBUM_ART || key == PreferenceUtil.KEEP_SCREEN_ON || key == PreferenceUtil.TOGGLE_SEPARATE_LINE || key == PreferenceUtil.ALBUM_GRID_STYLE || key == PreferenceUtil.ARTIST_GRID_STYLE || key == PreferenceUtil.TOGGLE_HOME_BANNER || key == PreferenceUtil.TOGGLE_ADD_CONTROLS || key == PreferenceUtil.ALBUM_COVER_STYLE || key == PreferenceUtil.HOME_ARTIST_GRID_STYLE || key == PreferenceUtil.ALBUM_COVER_TRANSFORM || key == PreferenceUtil.DESATURATED_COLOR || key == PreferenceUtil.TAB_TEXT_MODE || key == PreferenceUtil.LIBRARY_CATEGORIES
|
||||||
|
) postRecreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun selectedFragment(itemId: Int) {
|
private fun selectedFragment(itemId: Int) {
|
||||||
|
|
|
@ -20,7 +20,10 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropM
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager
|
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager
|
import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
||||||
import kotlinx.android.synthetic.main.activity_playing_queue.*
|
import kotlinx.android.synthetic.main.activity_playing_queue.clearQueue
|
||||||
|
import kotlinx.android.synthetic.main.activity_playing_queue.playerQueueSubHeader
|
||||||
|
import kotlinx.android.synthetic.main.activity_playing_queue.recyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_playing_queue.toolbar
|
||||||
|
|
||||||
open class PlayingQueueActivity : AbsMusicServiceActivity() {
|
open class PlayingQueueActivity : AbsMusicServiceActivity() {
|
||||||
|
|
||||||
|
@ -33,7 +36,10 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
|
||||||
|
|
||||||
private fun getUpNextAndQueueTime(): String {
|
private fun getUpNextAndQueueTime(): String {
|
||||||
val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position)
|
val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position)
|
||||||
return MusicUtil.buildInfoString(resources.getString(R.string.up_next), MusicUtil.getReadableDurationString(duration))
|
return MusicUtil.buildInfoString(
|
||||||
|
resources.getString(R.string.up_next),
|
||||||
|
MusicUtil.getReadableDurationString(duration)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -73,10 +79,10 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
|
||||||
animator.supportsChangeAnimations = false
|
animator.supportsChangeAnimations = false
|
||||||
|
|
||||||
playingQueueAdapter = PlayingQueueAdapter(
|
playingQueueAdapter = PlayingQueueAdapter(
|
||||||
this,
|
this,
|
||||||
MusicPlayerRemote.playingQueue,
|
MusicPlayerRemote.playingQueue,
|
||||||
MusicPlayerRemote.position,
|
MusicPlayerRemote.position,
|
||||||
R.layout.item_queue
|
R.layout.item_queue
|
||||||
)
|
)
|
||||||
wrappedAdapter = recyclerViewDragDropManager?.createWrappedAdapter(playingQueueAdapter!!)
|
wrappedAdapter = recyclerViewDragDropManager?.createWrappedAdapter(playingQueueAdapter!!)
|
||||||
wrappedAdapter = wrappedAdapter?.let { recyclerViewSwipeManager?.createWrappedAdapter(it) }
|
wrappedAdapter = wrappedAdapter?.let { recyclerViewSwipeManager?.createWrappedAdapter(it) }
|
||||||
|
@ -105,7 +111,6 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkForPadding() {
|
private fun checkForPadding() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueueChanged() {
|
override fun onQueueChanged() {
|
||||||
|
@ -178,14 +183,14 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() {
|
||||||
applyToolbar(toolbar)
|
applyToolbar(toolbar)
|
||||||
clearQueue.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
clearQueue.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
||||||
ColorStateList.valueOf(
|
ColorStateList.valueOf(
|
||||||
MaterialValueHelper.getPrimaryTextColor(
|
MaterialValueHelper.getPrimaryTextColor(
|
||||||
this,
|
this,
|
||||||
ColorUtil.isColorLight(
|
ColorUtil.isColorLight(
|
||||||
ThemeStore.accentColor(
|
ThemeStore.accentColor(
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
).apply {
|
).apply {
|
||||||
clearQueue.setTextColor(this)
|
clearQueue.setTextColor(this)
|
||||||
clearQueue.iconTint = this
|
clearQueue.iconTint = this
|
||||||
|
|
|
@ -29,7 +29,11 @@ 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
|
||||||
import kotlinx.android.synthetic.main.activity_playlist_detail.*
|
import kotlinx.android.synthetic.main.activity_playlist_detail.empty
|
||||||
|
import kotlinx.android.synthetic.main.activity_playlist_detail.emptyEmoji
|
||||||
|
import kotlinx.android.synthetic.main.activity_playlist_detail.emptyText
|
||||||
|
import kotlinx.android.synthetic.main.activity_playlist_detail.recyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_playlist_detail.toolbar
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, PlaylistSongsView {
|
class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, PlaylistSongsView {
|
||||||
|
@ -79,19 +83,25 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
|
||||||
recyclerViewDragDropManager = RecyclerViewDragDropManager()
|
recyclerViewDragDropManager = RecyclerViewDragDropManager()
|
||||||
val animator = RefactoredDefaultItemAnimator()
|
val animator = RefactoredDefaultItemAnimator()
|
||||||
adapter = OrderablePlaylistSongAdapter(this,
|
adapter = OrderablePlaylistSongAdapter(this,
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
R.layout.item_list,
|
R.layout.item_list,
|
||||||
false,
|
false,
|
||||||
this,
|
this,
|
||||||
object : OrderablePlaylistSongAdapter.OnMoveItemListener {
|
object : OrderablePlaylistSongAdapter.OnMoveItemListener {
|
||||||
override fun onMoveItem(fromPosition: Int, toPosition: Int) {
|
override fun onMoveItem(fromPosition: Int, toPosition: Int) {
|
||||||
if (PlaylistsUtil.moveItem(this@PlaylistDetailActivity, playlist.id, fromPosition, toPosition)) {
|
if (PlaylistsUtil.moveItem(
|
||||||
val song = adapter.dataSet.removeAt(fromPosition)
|
this@PlaylistDetailActivity,
|
||||||
adapter.dataSet.add(toPosition, song)
|
playlist.id,
|
||||||
adapter.notifyItemMoved(fromPosition, toPosition)
|
fromPosition,
|
||||||
}
|
toPosition
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
val song = adapter.dataSet.removeAt(fromPosition)
|
||||||
|
adapter.dataSet.add(toPosition, song)
|
||||||
|
adapter.notifyItemMoved(fromPosition, toPosition)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter)
|
wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter)
|
||||||
|
|
||||||
recyclerView.adapter = wrappedAdapter
|
recyclerView.adapter = wrappedAdapter
|
||||||
|
@ -120,8 +130,8 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(
|
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)
|
return super.onCreateOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
@ -140,7 +150,15 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
|
||||||
if (cab != null && cab!!.isActive) {
|
if (cab != null && cab!!.isActive) {
|
||||||
cab!!.finish()
|
cab!!.finish()
|
||||||
}
|
}
|
||||||
cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes).setCloseDrawableRes(R.drawable.ic_close_white_24dp).setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ATHUtil.resolveColor(this, R.attr.colorSurface))).start(callback)
|
cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes).setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||||
|
.setBackgroundColor(
|
||||||
|
RetroColorUtil.shiftBackgroundColorForLightText(
|
||||||
|
ATHUtil.resolveColor(
|
||||||
|
this,
|
||||||
|
R.attr.colorSurface
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).start(callback)
|
||||||
return cab!!
|
return cab!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,140 +14,143 @@ import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||||
import code.name.monkey.retromusic.extensions.applyToolbar
|
import code.name.monkey.retromusic.extensions.applyToolbar
|
||||||
import com.anjlab.android.iab.v3.BillingProcessor
|
import com.anjlab.android.iab.v3.BillingProcessor
|
||||||
import com.anjlab.android.iab.v3.TransactionDetails
|
import com.anjlab.android.iab.v3.TransactionDetails
|
||||||
import kotlinx.android.synthetic.main.activity_pro_version.*
|
import kotlinx.android.synthetic.main.activity_pro_version.purchaseButton
|
||||||
|
import kotlinx.android.synthetic.main.activity_pro_version.restoreButton
|
||||||
|
import kotlinx.android.synthetic.main.activity_pro_version.toolbar
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
|
class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
|
||||||
|
|
||||||
private lateinit var billingProcessor: BillingProcessor
|
private lateinit var billingProcessor: BillingProcessor
|
||||||
private var restorePurchaseAsyncTask: AsyncTask<*, *, *>? = null
|
private var restorePurchaseAsyncTask: AsyncTask<*, *, *>? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
setDrawUnderStatusBar()
|
setDrawUnderStatusBar()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_pro_version)
|
setContentView(R.layout.activity_pro_version)
|
||||||
setStatusbarColorAuto()
|
setStatusbarColorAuto()
|
||||||
setNavigationbarColorAuto()
|
setNavigationbarColorAuto()
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
applyToolbar(toolbar)
|
applyToolbar(toolbar)
|
||||||
|
|
||||||
restoreButton.isEnabled = false
|
restoreButton.isEnabled = false
|
||||||
purchaseButton.isEnabled = false
|
purchaseButton.isEnabled = false
|
||||||
|
|
||||||
billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY, this)
|
billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY, this)
|
||||||
|
|
||||||
MaterialUtil.setTint(restoreButton, false)
|
MaterialUtil.setTint(restoreButton, false)
|
||||||
MaterialUtil.setTint(purchaseButton, true)
|
MaterialUtil.setTint(purchaseButton, true)
|
||||||
|
|
||||||
restoreButton.setOnClickListener {
|
restoreButton.setOnClickListener {
|
||||||
if (restorePurchaseAsyncTask == null || restorePurchaseAsyncTask!!.status != AsyncTask.Status.RUNNING) {
|
if (restorePurchaseAsyncTask == null || restorePurchaseAsyncTask!!.status != AsyncTask.Status.RUNNING) {
|
||||||
restorePurchase()
|
restorePurchase()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
purchaseButton.setOnClickListener {
|
purchaseButton.setOnClickListener {
|
||||||
billingProcessor.purchase(this@PurchaseActivity, App.PRO_VERSION_PRODUCT_ID)
|
billingProcessor.purchase(this@PurchaseActivity, App.PRO_VERSION_PRODUCT_ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restorePurchase() {
|
private fun restorePurchase() {
|
||||||
if (restorePurchaseAsyncTask != null) {
|
if (restorePurchaseAsyncTask != null) {
|
||||||
restorePurchaseAsyncTask!!.cancel(false)
|
restorePurchaseAsyncTask!!.cancel(false)
|
||||||
}
|
}
|
||||||
restorePurchaseAsyncTask = RestorePurchaseAsyncTask(this).execute()
|
restorePurchaseAsyncTask = RestorePurchaseAsyncTask(this).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onProductPurchased(productId: String, details: TransactionDetails?) {
|
override fun onProductPurchased(productId: String, details: TransactionDetails?) {
|
||||||
Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show()
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPurchaseHistoryRestored() {
|
override fun onPurchaseHistoryRestored() {
|
||||||
if (App.isProVersion()) {
|
if (App.isProVersion()) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
R.string.restored_previous_purchase_please_restart,
|
R.string.restored_previous_purchase_please_restart,
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.no_purchase_found, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.no_purchase_found, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBillingError(errorCode: Int, error: Throwable?) {
|
override fun onBillingError(errorCode: Int, error: Throwable?) {
|
||||||
Log.e(TAG, "Billing error: code = $errorCode", error)
|
Log.e(TAG, "Billing error: code = $errorCode", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBillingInitialized() {
|
override fun onBillingInitialized() {
|
||||||
restoreButton.isEnabled = true
|
restoreButton.isEnabled = true
|
||||||
purchaseButton.isEnabled = true
|
purchaseButton.isEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
if (!billingProcessor.handleActivityResult(requestCode, resultCode, data)) {
|
if (!billingProcessor.handleActivityResult(requestCode, resultCode, data)) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> finish()
|
android.R.id.home -> finish()
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
billingProcessor.release()
|
billingProcessor.release()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RestorePurchaseAsyncTask internal constructor(purchaseActivity: PurchaseActivity) : AsyncTask<Void, Void, Boolean>() {
|
private class RestorePurchaseAsyncTask internal constructor(purchaseActivity: PurchaseActivity) :
|
||||||
|
AsyncTask<Void, Void, Boolean>() {
|
||||||
|
|
||||||
private val buyActivityWeakReference: WeakReference<PurchaseActivity> = WeakReference(
|
private val buyActivityWeakReference: WeakReference<PurchaseActivity> = WeakReference(
|
||||||
purchaseActivity
|
purchaseActivity
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun onPreExecute() {
|
override fun onPreExecute() {
|
||||||
super.onPreExecute()
|
super.onPreExecute()
|
||||||
val purchaseActivity = buyActivityWeakReference.get()
|
val purchaseActivity = buyActivityWeakReference.get()
|
||||||
if (purchaseActivity != null) {
|
if (purchaseActivity != null) {
|
||||||
Toast.makeText(purchaseActivity, R.string.restoring_purchase, Toast.LENGTH_SHORT)
|
Toast.makeText(purchaseActivity, R.string.restoring_purchase, Toast.LENGTH_SHORT)
|
||||||
.show()
|
.show()
|
||||||
} else {
|
} else {
|
||||||
cancel(false)
|
cancel(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doInBackground(vararg params: Void): Boolean? {
|
override fun doInBackground(vararg params: Void): Boolean? {
|
||||||
val purchaseActivity = buyActivityWeakReference.get()
|
val purchaseActivity = buyActivityWeakReference.get()
|
||||||
if (purchaseActivity != null) {
|
if (purchaseActivity != null) {
|
||||||
return purchaseActivity.billingProcessor.loadOwnedPurchasesFromGoogle()
|
return purchaseActivity.billingProcessor.loadOwnedPurchasesFromGoogle()
|
||||||
}
|
}
|
||||||
cancel(false)
|
cancel(false)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPostExecute(b: Boolean?) {
|
override fun onPostExecute(b: Boolean?) {
|
||||||
super.onPostExecute(b)
|
super.onPostExecute(b)
|
||||||
val purchaseActivity = buyActivityWeakReference.get()
|
val purchaseActivity = buyActivityWeakReference.get()
|
||||||
if (purchaseActivity == null || b == null) {
|
if (purchaseActivity == null || b == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b) {
|
if (b) {
|
||||||
purchaseActivity.onPurchaseHistoryRestored()
|
purchaseActivity.onPurchaseHistoryRestored()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
purchaseActivity,
|
purchaseActivity,
|
||||||
R.string.could_not_restore_purchase,
|
R.string.could_not_restore_purchase,
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG: String = "PurchaseActivity"
|
private const val TAG: String = "PurchaseActivity"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,17 @@ import code.name.monkey.retromusic.mvp.presenter.SearchPresenter
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SearchView
|
import code.name.monkey.retromusic.mvp.presenter.SearchView
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import kotlinx.android.synthetic.main.activity_search.*
|
import kotlinx.android.synthetic.main.activity_search.appBarLayout
|
||||||
import java.util.*
|
import kotlinx.android.synthetic.main.activity_search.back
|
||||||
|
import kotlinx.android.synthetic.main.activity_search.clearText
|
||||||
|
import kotlinx.android.synthetic.main.activity_search.empty
|
||||||
|
import kotlinx.android.synthetic.main.activity_search.keyboardPopup
|
||||||
|
import kotlinx.android.synthetic.main.activity_search.recyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_search.searchContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_search.searchView
|
||||||
|
import kotlinx.android.synthetic.main.activity_search.voiceSearch
|
||||||
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher, SearchView {
|
class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher, SearchView {
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -73,7 +80,7 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
|
|
||||||
keyboardPopup.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
keyboardPopup.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
||||||
ColorStateList.valueOf(
|
ColorStateList.valueOf(
|
||||||
MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(ThemeStore.accentColor(this)))
|
MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(ThemeStore.accentColor(this)))
|
||||||
).apply {
|
).apply {
|
||||||
keyboardPopup.setTextColor(this)
|
keyboardPopup.setTextColor(this)
|
||||||
keyboardPopup.iconTint = this
|
keyboardPopup.iconTint = this
|
||||||
|
@ -81,7 +88,6 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
query = savedInstanceState.getString(QUERY)
|
query = savedInstanceState.getString(QUERY)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
|
@ -181,8 +187,8 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
private fun startMicSearch() {
|
private fun startMicSearch() {
|
||||||
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
||||||
intent.putExtra(
|
intent.putExtra(
|
||||||
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
|
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
|
||||||
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
|
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
|
||||||
)
|
)
|
||||||
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
|
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
|
||||||
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
|
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
|
||||||
|
@ -191,13 +197,11 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT)
|
Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
@ -205,7 +209,6 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -5,139 +5,142 @@ import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.*
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.view.*
|
import android.view.KeyEvent
|
||||||
|
import android.view.View
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
|
||||||
abstract class AbsBaseActivity : AbsThemeActivity() {
|
abstract class AbsBaseActivity : AbsThemeActivity() {
|
||||||
private var hadPermissions: Boolean = false
|
private var hadPermissions: Boolean = false
|
||||||
private lateinit var permissions: Array<String>
|
private lateinit var permissions: Array<String>
|
||||||
private var permissionDeniedMessage: String? = null
|
private var permissionDeniedMessage: String? = null
|
||||||
|
|
||||||
open fun getPermissionsToRequest(): Array<String> {
|
open fun getPermissionsToRequest(): Array<String> {
|
||||||
return arrayOf()
|
return arrayOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun setPermissionDeniedMessage(message: String) {
|
protected fun setPermissionDeniedMessage(message: String) {
|
||||||
permissionDeniedMessage = message
|
permissionDeniedMessage = message
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPermissionDeniedMessage(): String {
|
fun getPermissionDeniedMessage(): String {
|
||||||
return if (permissionDeniedMessage == null) getString(code.name.monkey.retromusic.R.string.permissions_denied) else permissionDeniedMessage!!
|
return if (permissionDeniedMessage == null) getString(R.string.permissions_denied) else permissionDeniedMessage!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private val snackBarContainer: View
|
private val snackBarContainer: View
|
||||||
get() = window.decorView
|
get() = window.decorView
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
volumeControlStream = AudioManager.STREAM_MUSIC
|
volumeControlStream = AudioManager.STREAM_MUSIC
|
||||||
permissions = getPermissionsToRequest()
|
permissions = getPermissionsToRequest()
|
||||||
hadPermissions = hasPermissions()
|
hadPermissions = hasPermissions()
|
||||||
permissionDeniedMessage = null
|
permissionDeniedMessage = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||||
super.onPostCreate(savedInstanceState)
|
super.onPostCreate(savedInstanceState)
|
||||||
if (!hasPermissions()) {
|
if (!hasPermissions()) {
|
||||||
requestPermissions()
|
requestPermissions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
val hasPermissions = hasPermissions()
|
val hasPermissions = hasPermissions()
|
||||||
if (hasPermissions != hadPermissions) {
|
if (hasPermissions != hadPermissions) {
|
||||||
hadPermissions = hasPermissions
|
hadPermissions = hasPermissions
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
onHasPermissionsChanged(hasPermissions)
|
onHasPermissionsChanged(hasPermissions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun onHasPermissionsChanged(hasPermissions: Boolean) {
|
protected open fun onHasPermissionsChanged(hasPermissions: Boolean) {
|
||||||
// implemented by sub classes
|
// implemented by sub classes
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||||
if (event.keyCode == KeyEvent.KEYCODE_MENU && event.action == KeyEvent.ACTION_UP) {
|
if (event.keyCode == KeyEvent.KEYCODE_MENU && event.action == KeyEvent.ACTION_UP) {
|
||||||
showOverflowMenu()
|
showOverflowMenu()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun showOverflowMenu() {
|
protected fun showOverflowMenu() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
protected open fun requestPermissions() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
requestPermissions(permissions, PERMISSION_REQUEST)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun requestPermissions() {
|
protected fun hasPermissions(): Boolean {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
requestPermissions(permissions, PERMISSION_REQUEST)
|
for (permission in permissions) {
|
||||||
}
|
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
|
||||||
}
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
protected fun hasPermissions(): Boolean {
|
override fun onRequestPermissionsResult(
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
requestCode: Int,
|
||||||
for (permission in permissions) {
|
permissions: Array<String>,
|
||||||
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
|
grantResults: IntArray
|
||||||
return false
|
) {
|
||||||
}
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
}
|
if (requestCode == PERMISSION_REQUEST) {
|
||||||
}
|
for (grantResult in grantResults) {
|
||||||
return true
|
if (grantResult != PackageManager.PERMISSION_GRANTED) {
|
||||||
}
|
if (ActivityCompat.shouldShowRequestPermissionRationale(
|
||||||
|
this@AbsBaseActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
//User has deny from permission dialog
|
||||||
|
Snackbar.make(
|
||||||
|
snackBarContainer,
|
||||||
|
permissionDeniedMessage!!,
|
||||||
|
Snackbar.LENGTH_INDEFINITE
|
||||||
|
)
|
||||||
|
.setAction(code.name.monkey.retromusic.R.string.action_grant) { requestPermissions() }
|
||||||
|
.setActionTextColor(ThemeStore.accentColor(this)).show()
|
||||||
|
} else {
|
||||||
|
// User has deny permission and checked never show permission dialog so you can redirect to Application settings page
|
||||||
|
Snackbar.make(
|
||||||
|
snackBarContainer,
|
||||||
|
permissionDeniedMessage!!,
|
||||||
|
Snackbar.LENGTH_INDEFINITE
|
||||||
|
).setAction(code.name.monkey.retromusic.R.string.action_settings) {
|
||||||
|
val intent = Intent()
|
||||||
|
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||||
|
val uri = Uri.fromParts(
|
||||||
|
"package",
|
||||||
|
this@AbsBaseActivity.packageName,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
intent.data = uri
|
||||||
|
startActivity(intent)
|
||||||
|
}.setActionTextColor(ThemeStore.accentColor(this)).show()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hadPermissions = true
|
||||||
|
onHasPermissionsChanged(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(
|
companion object {
|
||||||
requestCode: Int,
|
const val PERMISSION_REQUEST = 100
|
||||||
permissions: Array<String>,
|
}
|
||||||
grantResults: IntArray
|
|
||||||
) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
|
||||||
if (requestCode == PERMISSION_REQUEST) {
|
|
||||||
for (grantResult in grantResults) {
|
|
||||||
if (grantResult != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
if (ActivityCompat.shouldShowRequestPermissionRationale(
|
|
||||||
this@AbsBaseActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
||||||
)) {
|
|
||||||
//User has deny from permission dialog
|
|
||||||
Snackbar.make(
|
|
||||||
snackBarContainer,
|
|
||||||
permissionDeniedMessage!!,
|
|
||||||
Snackbar.LENGTH_INDEFINITE
|
|
||||||
)
|
|
||||||
.setAction(code.name.monkey.retromusic.R.string.action_grant) { requestPermissions() }
|
|
||||||
.setActionTextColor(ThemeStore.accentColor(this)).show()
|
|
||||||
} else {
|
|
||||||
// User has deny permission and checked never show permission dialog so you can redirect to Application settings page
|
|
||||||
Snackbar.make(
|
|
||||||
snackBarContainer,
|
|
||||||
permissionDeniedMessage!!,
|
|
||||||
Snackbar.LENGTH_INDEFINITE
|
|
||||||
).setAction(code.name.monkey.retromusic.R.string.action_settings) {
|
|
||||||
val intent = Intent()
|
|
||||||
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
|
||||||
val uri = Uri.fromParts(
|
|
||||||
"package",
|
|
||||||
this@AbsBaseActivity.packageName,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
intent.data = uri
|
|
||||||
startActivity(intent)
|
|
||||||
}.setActionTextColor(ThemeStore.accentColor(this)).show()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hadPermissions = true
|
|
||||||
onHasPermissionsChanged(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val PERMISSION_REQUEST = 100
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,167 +1,179 @@
|
||||||
package code.name.monkey.retromusic.activities.base
|
package code.name.monkey.retromusic.activities.base
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.*
|
import android.content.BroadcastReceiver
|
||||||
import android.os.*
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.IBinder
|
||||||
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.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
import code.name.monkey.retromusic.service.MusicService.*
|
import code.name.monkey.retromusic.service.MusicService.FAVORITE_STATE_CHANGED
|
||||||
|
import code.name.monkey.retromusic.service.MusicService.MEDIA_STORE_CHANGED
|
||||||
|
import code.name.monkey.retromusic.service.MusicService.META_CHANGED
|
||||||
|
import code.name.monkey.retromusic.service.MusicService.PLAY_STATE_CHANGED
|
||||||
|
import code.name.monkey.retromusic.service.MusicService.QUEUE_CHANGED
|
||||||
|
import code.name.monkey.retromusic.service.MusicService.REPEAT_MODE_CHANGED
|
||||||
|
import code.name.monkey.retromusic.service.MusicService.SHUFFLE_MODE_CHANGED
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
|
|
||||||
abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener {
|
abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener {
|
||||||
|
|
||||||
private val mMusicServiceEventListeners = ArrayList<MusicServiceEventListener>()
|
private val mMusicServiceEventListeners = ArrayList<MusicServiceEventListener>()
|
||||||
|
|
||||||
private var serviceToken: MusicPlayerRemote.ServiceToken? = null
|
private var serviceToken: MusicPlayerRemote.ServiceToken? = null
|
||||||
private var musicStateReceiver: MusicStateReceiver? = null
|
private var musicStateReceiver: MusicStateReceiver? = null
|
||||||
private var receiverRegistered: Boolean = false
|
private var receiverRegistered: Boolean = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
serviceToken = MusicPlayerRemote.bindToService(this, object : ServiceConnection {
|
serviceToken = MusicPlayerRemote.bindToService(this, object : ServiceConnection {
|
||||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||||
this@AbsMusicServiceActivity.onServiceConnected()
|
this@AbsMusicServiceActivity.onServiceConnected()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName) {
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
this@AbsMusicServiceActivity.onServiceDisconnected()
|
this@AbsMusicServiceActivity.onServiceDisconnected()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setPermissionDeniedMessage(getString(R.string.permission_external_storage_denied));
|
setPermissionDeniedMessage(getString(R.string.permission_external_storage_denied))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
MusicPlayerRemote.unbindFromService(serviceToken)
|
MusicPlayerRemote.unbindFromService(serviceToken)
|
||||||
if (receiverRegistered) {
|
if (receiverRegistered) {
|
||||||
unregisterReceiver(musicStateReceiver)
|
unregisterReceiver(musicStateReceiver)
|
||||||
receiverRegistered = false
|
receiverRegistered = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addMusicServiceEventListener(listener: MusicServiceEventListener?) {
|
fun addMusicServiceEventListener(listener: MusicServiceEventListener?) {
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
mMusicServiceEventListeners.add(listener)
|
mMusicServiceEventListeners.add(listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeMusicServiceEventListener(listener: MusicServiceEventListener?) {
|
fun removeMusicServiceEventListener(listener: MusicServiceEventListener?) {
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
mMusicServiceEventListeners.remove(listener)
|
mMusicServiceEventListeners.remove(listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
override fun onServiceConnected() {
|
||||||
if (!receiverRegistered) {
|
if (!receiverRegistered) {
|
||||||
musicStateReceiver = MusicStateReceiver(this)
|
musicStateReceiver = MusicStateReceiver(this)
|
||||||
|
|
||||||
val filter = IntentFilter()
|
val filter = IntentFilter()
|
||||||
filter.addAction(PLAY_STATE_CHANGED)
|
filter.addAction(PLAY_STATE_CHANGED)
|
||||||
filter.addAction(SHUFFLE_MODE_CHANGED)
|
filter.addAction(SHUFFLE_MODE_CHANGED)
|
||||||
filter.addAction(REPEAT_MODE_CHANGED)
|
filter.addAction(REPEAT_MODE_CHANGED)
|
||||||
filter.addAction(META_CHANGED)
|
filter.addAction(META_CHANGED)
|
||||||
filter.addAction(QUEUE_CHANGED)
|
filter.addAction(QUEUE_CHANGED)
|
||||||
filter.addAction(MEDIA_STORE_CHANGED)
|
filter.addAction(MEDIA_STORE_CHANGED)
|
||||||
filter.addAction(FAVORITE_STATE_CHANGED)
|
filter.addAction(FAVORITE_STATE_CHANGED)
|
||||||
|
|
||||||
registerReceiver(musicStateReceiver, filter)
|
registerReceiver(musicStateReceiver, filter)
|
||||||
|
|
||||||
receiverRegistered = true
|
receiverRegistered = true
|
||||||
}
|
}
|
||||||
|
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onServiceConnected()
|
listener.onServiceConnected()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected() {
|
override fun onServiceDisconnected() {
|
||||||
if (receiverRegistered) {
|
if (receiverRegistered) {
|
||||||
unregisterReceiver(musicStateReceiver)
|
unregisterReceiver(musicStateReceiver)
|
||||||
receiverRegistered = false
|
receiverRegistered = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onServiceDisconnected()
|
listener.onServiceDisconnected()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayingMetaChanged() {
|
override fun onPlayingMetaChanged() {
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onPlayingMetaChanged()
|
listener.onPlayingMetaChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueueChanged() {
|
override fun onQueueChanged() {
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onQueueChanged()
|
listener.onQueueChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayStateChanged() {
|
override fun onPlayStateChanged() {
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onPlayStateChanged()
|
listener.onPlayStateChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaStoreChanged() {
|
override fun onMediaStoreChanged() {
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onMediaStoreChanged()
|
listener.onMediaStoreChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRepeatModeChanged() {
|
override fun onRepeatModeChanged() {
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onRepeatModeChanged()
|
listener.onRepeatModeChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onShuffleModeChanged() {
|
override fun onShuffleModeChanged() {
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onShuffleModeChanged()
|
listener.onShuffleModeChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onHasPermissionsChanged(hasPermissions: Boolean) {
|
override fun onHasPermissionsChanged(hasPermissions: Boolean) {
|
||||||
super.onHasPermissionsChanged(hasPermissions)
|
super.onHasPermissionsChanged(hasPermissions)
|
||||||
val intent = Intent(MEDIA_STORE_CHANGED)
|
val intent = Intent(MEDIA_STORE_CHANGED)
|
||||||
intent.putExtra(
|
intent.putExtra(
|
||||||
"from_permissions_changed",
|
"from_permissions_changed",
|
||||||
true
|
true
|
||||||
) // just in case we need to know this at some point
|
) // just in case we need to know this at some point
|
||||||
sendBroadcast(intent)
|
sendBroadcast(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPermissionsToRequest(): Array<String> {
|
override fun getPermissionsToRequest(): Array<String> {
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MusicStateReceiver(activity: AbsMusicServiceActivity) : BroadcastReceiver() {
|
private class MusicStateReceiver(activity: AbsMusicServiceActivity) : BroadcastReceiver() {
|
||||||
|
|
||||||
private val reference: WeakReference<AbsMusicServiceActivity> = WeakReference(activity)
|
private val reference: WeakReference<AbsMusicServiceActivity> = WeakReference(activity)
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val action = intent.action
|
val action = intent.action
|
||||||
val activity = reference.get()
|
val activity = reference.get()
|
||||||
if (activity != null && action != null) {
|
if (activity != null && action != null) {
|
||||||
when (action) {
|
when (action) {
|
||||||
FAVORITE_STATE_CHANGED, META_CHANGED -> activity.onPlayingMetaChanged()
|
FAVORITE_STATE_CHANGED, META_CHANGED -> activity.onPlayingMetaChanged()
|
||||||
QUEUE_CHANGED -> activity.onQueueChanged()
|
QUEUE_CHANGED -> activity.onQueueChanged()
|
||||||
PLAY_STATE_CHANGED -> activity.onPlayStateChanged()
|
PLAY_STATE_CHANGED -> activity.onPlayStateChanged()
|
||||||
REPEAT_MODE_CHANGED -> activity.onRepeatModeChanged()
|
REPEAT_MODE_CHANGED -> activity.onRepeatModeChanged()
|
||||||
SHUFFLE_MODE_CHANGED -> activity.onShuffleModeChanged()
|
SHUFFLE_MODE_CHANGED -> activity.onShuffleModeChanged()
|
||||||
MEDIA_STORE_CHANGED -> activity.onMediaStoreChanged()
|
MEDIA_STORE_CHANGED -> activity.onMediaStoreChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val TAG: String = AbsMusicServiceActivity::class.java.simpleName
|
val TAG: String = AbsMusicServiceActivity::class.java.simpleName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,20 @@ 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.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.ADAPTIVE
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR_CARD
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.CARD
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.COLOR
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.FIT
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.FLAT
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.FULL
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.MATERIAL
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.NORMAL
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.PEAK
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.PLAIN
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.SIMPLE
|
||||||
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.TINY
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.adaptive.AdaptiveFragment
|
import code.name.monkey.retromusic.fragments.player.adaptive.AdaptiveFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.blur.BlurPlayerFragment
|
import code.name.monkey.retromusic.fragments.player.blur.BlurPlayerFragment
|
||||||
|
@ -38,7 +51,9 @@ 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
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import kotlinx.android.synthetic.main.sliding_music_panel_layout.*
|
import kotlinx.android.synthetic.main.sliding_music_panel_layout.bottomNavigationView
|
||||||
|
import kotlinx.android.synthetic.main.sliding_music_panel_layout.dimBackground
|
||||||
|
import kotlinx.android.synthetic.main.sliding_music_panel_layout.slidingPanel
|
||||||
|
|
||||||
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlayerFragment.Callbacks {
|
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlayerFragment.Callbacks {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -205,7 +220,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay
|
||||||
slidingPanel.cardElevation = DensityUtil.dip2px(this, 10f).toFloat()
|
slidingPanel.cardElevation = DensityUtil.dip2px(this, 10f).toFloat()
|
||||||
bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat()
|
bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat()
|
||||||
bottomSheetBehavior.isHideable = false
|
bottomSheetBehavior.isHideable = false
|
||||||
bottomSheetBehavior.peekHeight = if (bottomNavigationView.visibility == View.VISIBLE) heightOfBarWithTabs else heightOfBar
|
bottomSheetBehavior.peekHeight =
|
||||||
|
if (bottomNavigationView.visibility == View.VISIBLE) heightOfBarWithTabs else heightOfBar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +252,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay
|
||||||
else -> PlayerFragment()
|
else -> PlayerFragment()
|
||||||
} // must implement AbsPlayerFragment
|
} // must implement AbsPlayerFragment
|
||||||
supportFragmentManager.beginTransaction().replace(R.id.playerFragmentContainer, fragment)
|
supportFragmentManager.beginTransaction().replace(R.id.playerFragmentContainer, fragment)
|
||||||
.commit()
|
.commit()
|
||||||
supportFragmentManager.executePendingTransactions()
|
supportFragmentManager.executePendingTransactions()
|
||||||
|
|
||||||
playerFragment = supportFragmentManager.findFragmentById(R.id.playerFragmentContainer) as AbsPlayerFragment
|
playerFragment = supportFragmentManager.findFragmentById(R.id.playerFragmentContainer) as AbsPlayerFragment
|
||||||
|
@ -292,7 +308,14 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay
|
||||||
super.setLightNavigationBar(isColorLight)
|
super.setLightNavigationBar(isColorLight)
|
||||||
super.setLightStatusbar(isColorLight)
|
super.setLightStatusbar(isColorLight)
|
||||||
} else {
|
} else {
|
||||||
super.setLightStatusbar(ColorUtil.isColorLight(ATHUtil.resolveColor(this, android.R.attr.windowBackground)))
|
super.setLightStatusbar(
|
||||||
|
ColorUtil.isColorLight(
|
||||||
|
ATHUtil.resolveColor(
|
||||||
|
this,
|
||||||
|
android.R.attr.windowBackground
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
super.setLightNavigationBar(true)
|
super.setLightNavigationBar(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,8 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
var background: Drawable? = if (PreferenceUtil.getInstance(this).isRoundCorners)
|
var background: Drawable? = if (PreferenceUtil.getInstance(this).isRoundCorners)
|
||||||
ContextCompat.getDrawable(this, R.drawable.round_window)
|
ContextCompat.getDrawable(this, R.drawable.round_window)
|
||||||
else ContextCompat.getDrawable(this, R.drawable.square_window)
|
else ContextCompat.getDrawable(this, R.drawable.square_window)
|
||||||
background = TintHelper.createTintedDrawable(background, ATHUtil.resolveColor(this, android.R.attr.windowBackground))
|
background =
|
||||||
|
TintHelper.createTintedDrawable(background, ATHUtil.resolveColor(this, android.R.attr.windowBackground))
|
||||||
window.setBackgroundDrawable(background)
|
window.setBackgroundDrawable(background)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +159,8 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setImmersiveFullscreen() {
|
private fun setImmersiveFullscreen() {
|
||||||
val flags = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
|
val flags =
|
||||||
|
(View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
|
||||||
|
|
||||||
if (PreferenceUtil.getInstance(this).fullScreenMode) {
|
if (PreferenceUtil.getInstance(this).fullScreenMode) {
|
||||||
window.decorView.systemUiVisibility = flags
|
window.decorView.systemUiVisibility = flags
|
||||||
|
@ -190,6 +192,5 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
handler.postDelayed(this, 500)
|
handler.postDelayed(this, 500)
|
||||||
}
|
}
|
||||||
return super.onKeyDown(keyCode, event)
|
return super.onKeyDown(keyCode, event)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,9 +32,19 @@ import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.callbacks.onCancel
|
import com.afollestad.materialdialogs.callbacks.onCancel
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import kotlinx.android.synthetic.main.activity_bug_report.*
|
import kotlinx.android.synthetic.main.activity_bug_report.sendFab
|
||||||
import kotlinx.android.synthetic.main.bug_report_card_device_info.*
|
import kotlinx.android.synthetic.main.activity_bug_report.toolbar
|
||||||
import kotlinx.android.synthetic.main.bug_report_card_report.*
|
import kotlinx.android.synthetic.main.bug_report_card_device_info.airTextDeviceInfo
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputDescription
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutDescription
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutPassword
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutTitle
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputLayoutUsername
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputPassword
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputTitle
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.inputUsername
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.optionAnonymous
|
||||||
|
import kotlinx.android.synthetic.main.bug_report_card_report.optionUseAccount
|
||||||
import org.eclipse.egit.github.core.Issue
|
import org.eclipse.egit.github.core.Issue
|
||||||
import org.eclipse.egit.github.core.client.GitHubClient
|
import org.eclipse.egit.github.core.client.GitHubClient
|
||||||
import org.eclipse.egit.github.core.client.RequestException
|
import org.eclipse.egit.github.core.client.RequestException
|
||||||
|
@ -48,11 +58,11 @@ private const val RESULT_ISSUES_NOT_ENABLED = "RESULT_ISSUES_NOT_ENABLED"
|
||||||
private const val RESULT_UNKNOWN = "RESULT_UNKNOWN"
|
private const val RESULT_UNKNOWN = "RESULT_UNKNOWN"
|
||||||
|
|
||||||
@StringDef(
|
@StringDef(
|
||||||
RESULT_SUCCESS,
|
RESULT_SUCCESS,
|
||||||
RESULT_BAD_CREDENTIALS,
|
RESULT_BAD_CREDENTIALS,
|
||||||
RESULT_INVALID_TOKEN,
|
RESULT_INVALID_TOKEN,
|
||||||
RESULT_ISSUES_NOT_ENABLED,
|
RESULT_ISSUES_NOT_ENABLED,
|
||||||
RESULT_UNKNOWN
|
RESULT_UNKNOWN
|
||||||
)
|
)
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
private annotation class Result
|
private annotation class Result
|
||||||
|
@ -157,9 +167,9 @@ open class BugReportActivity : AbsThemeActivity() {
|
||||||
val clip = ClipData.newPlainText(getString(R.string.device_info), deviceInfo?.toMarkdown())
|
val clip = ClipData.newPlainText(getString(R.string.device_info), deviceInfo?.toMarkdown())
|
||||||
clipboard.setPrimaryClip(clip)
|
clipboard.setPrimaryClip(clip)
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this@BugReportActivity,
|
this@BugReportActivity,
|
||||||
R.string.copied_device_info_to_clipboard,
|
R.string.copied_device_info_to_clipboard,
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,11 +242,12 @@ open class BugReportActivity : AbsThemeActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ReportIssueAsyncTask private constructor(
|
private class ReportIssueAsyncTask private constructor(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
private val report: Report,
|
private val report: Report,
|
||||||
private val target: GithubTarget,
|
private val target: GithubTarget,
|
||||||
private val login: GithubLogin
|
private val login: GithubLogin
|
||||||
) : DialogAsyncTask<Void, Void, String>(activity) {
|
) : DialogAsyncTask<Void, Void, String>(activity) {
|
||||||
|
|
||||||
override fun createDialog(context: Context): Dialog {
|
override fun createDialog(context: Context): Dialog {
|
||||||
return AlertDialog.Builder(context).show()
|
return AlertDialog.Builder(context).show()
|
||||||
}
|
}
|
||||||
|
@ -268,7 +279,6 @@ open class BugReportActivity : AbsThemeActivity() {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
return RESULT_UNKNOWN
|
return RESULT_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPostExecute(@Result result: String) {
|
override fun onPostExecute(@Result result: String) {
|
||||||
|
@ -312,10 +322,10 @@ open class BugReportActivity : AbsThemeActivity() {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun report(
|
fun report(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
report: Report,
|
report: Report,
|
||||||
target: GithubTarget,
|
target: GithubTarget,
|
||||||
login: GithubLogin
|
login: GithubLogin
|
||||||
) {
|
) {
|
||||||
ReportIssueAsyncTask(activity, report, target, login).execute()
|
ReportIssueAsyncTask(activity, report, target, login).execute()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,41 +5,56 @@ import android.content.Context;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import androidx.annotation.IntRange;
|
import androidx.annotation.IntRange;
|
||||||
|
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
|
||||||
|
|
||||||
public class DeviceInfo {
|
public class DeviceInfo {
|
||||||
private final int versionCode;
|
|
||||||
private final String versionName;
|
|
||||||
private final String buildVersion = Build.VERSION.INCREMENTAL;
|
|
||||||
private final String releaseVersion = Build.VERSION.RELEASE;
|
|
||||||
@IntRange(from = 0)
|
|
||||||
private final int sdkVersion = Build.VERSION.SDK_INT;
|
|
||||||
private final String buildID = Build.DISPLAY;
|
|
||||||
private final String brand = Build.BRAND;
|
|
||||||
private final String manufacturer = Build.MANUFACTURER;
|
|
||||||
private final String device = Build.DEVICE;
|
|
||||||
private final String model = Build.MODEL;
|
|
||||||
private final String product = Build.PRODUCT;
|
|
||||||
private final String hardware = Build.HARDWARE;
|
|
||||||
private final String baseTheme;
|
|
||||||
private final String nowPlayingTheme;
|
|
||||||
private final boolean isAdaptive;
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private final String[] abis = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
private final String[] abis = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||||
Build.SUPPORTED_ABIS : new String[]{Build.CPU_ABI, Build.CPU_ABI2};
|
Build.SUPPORTED_ABIS : new String[]{Build.CPU_ABI, Build.CPU_ABI2};
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private final String[] abis32Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
private final String[] abis32Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||||
Build.SUPPORTED_32_BIT_ABIS : null;
|
Build.SUPPORTED_32_BIT_ABIS : null;
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private final String[] abis64Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
private final String[] abis64Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||||
Build.SUPPORTED_64_BIT_ABIS : null;
|
Build.SUPPORTED_64_BIT_ABIS : null;
|
||||||
|
|
||||||
|
private final String baseTheme;
|
||||||
|
|
||||||
|
private final String brand = Build.BRAND;
|
||||||
|
|
||||||
|
private final String buildID = Build.DISPLAY;
|
||||||
|
|
||||||
|
private final String buildVersion = Build.VERSION.INCREMENTAL;
|
||||||
|
|
||||||
|
private final String device = Build.DEVICE;
|
||||||
|
|
||||||
|
private final String hardware = Build.HARDWARE;
|
||||||
|
|
||||||
|
private final boolean isAdaptive;
|
||||||
|
|
||||||
|
private final String manufacturer = Build.MANUFACTURER;
|
||||||
|
|
||||||
|
private final String model = Build.MODEL;
|
||||||
|
|
||||||
|
private final String nowPlayingTheme;
|
||||||
|
|
||||||
|
private final String product = Build.PRODUCT;
|
||||||
|
|
||||||
|
private final String releaseVersion = Build.VERSION.RELEASE;
|
||||||
|
|
||||||
|
@IntRange(from = 0)
|
||||||
|
private final int sdkVersion = Build.VERSION.SDK_INT;
|
||||||
|
|
||||||
|
private final int versionCode;
|
||||||
|
|
||||||
|
private final String versionName;
|
||||||
|
|
||||||
public DeviceInfo(Context context) {
|
public DeviceInfo(Context context) {
|
||||||
PackageInfo packageInfo;
|
PackageInfo packageInfo;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -4,7 +4,6 @@ package code.name.monkey.retromusic.activities.bugreport.model;
|
||||||
import code.name.monkey.retromusic.activities.bugreport.model.github.ExtraInfo;
|
import code.name.monkey.retromusic.activities.bugreport.model.github.ExtraInfo;
|
||||||
|
|
||||||
public class Report {
|
public class Report {
|
||||||
private final String title;
|
|
||||||
|
|
||||||
private final String description;
|
private final String description;
|
||||||
|
|
||||||
|
@ -12,6 +11,8 @@ public class Report {
|
||||||
|
|
||||||
private final ExtraInfo extraInfo;
|
private final ExtraInfo extraInfo;
|
||||||
|
|
||||||
|
private final String title;
|
||||||
|
|
||||||
public Report(String title, String description, DeviceInfo deviceInfo, ExtraInfo extraInfo) {
|
public Report(String title, String description, DeviceInfo deviceInfo, ExtraInfo extraInfo) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
@ -19,14 +20,14 @@ public class Report {
|
||||||
this.extraInfo = extraInfo;
|
this.extraInfo = extraInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description + "\n\n"
|
return description + "\n\n"
|
||||||
+ "-\n\n"
|
+ "-\n\n"
|
||||||
+ deviceInfo.toMarkdown() + "\n\n"
|
+ deviceInfo.toMarkdown() + "\n\n"
|
||||||
+ extraInfo.toMarkdown();
|
+ extraInfo.toMarkdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ExtraInfo {
|
public class ExtraInfo {
|
||||||
|
|
||||||
private final Map<String, String> extraInfo = new LinkedHashMap<>();
|
private final Map<String, String> extraInfo = new LinkedHashMap<>();
|
||||||
|
|
||||||
public void put(String key, String value) {
|
public void put(String key, String value) {
|
||||||
|
@ -39,7 +40,9 @@ public class ExtraInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toMarkdown() {
|
public String toMarkdown() {
|
||||||
if (extraInfo.isEmpty()) return "";
|
if (extraInfo.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output = new StringBuilder();
|
||||||
output.append("Extra info:\n"
|
output.append("Extra info:\n"
|
||||||
|
|
|
@ -3,11 +3,12 @@ package code.name.monkey.retromusic.activities.bugreport.model.github;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
public class GithubLogin {
|
public class GithubLogin {
|
||||||
private final String username;
|
|
||||||
|
private final String apiToken;
|
||||||
|
|
||||||
private final String password;
|
private final String password;
|
||||||
|
|
||||||
private final String apiToken;
|
private final String username;
|
||||||
|
|
||||||
public GithubLogin(String username, String password) {
|
public GithubLogin(String username, String password) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
@ -21,20 +22,20 @@ public class GithubLogin {
|
||||||
this.apiToken = apiToken;
|
this.apiToken = apiToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getApiToken() {
|
||||||
return username;
|
return apiToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean shouldUseApiToken() {
|
public boolean shouldUseApiToken() {
|
||||||
return TextUtils.isEmpty(username) || TextUtils.isEmpty(password);
|
return TextUtils.isEmpty(username) || TextUtils.isEmpty(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getApiToken() {
|
|
||||||
return apiToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
package code.name.monkey.retromusic.activities.bugreport.model.github;
|
package code.name.monkey.retromusic.activities.bugreport.model.github;
|
||||||
|
|
||||||
public class GithubTarget {
|
public class GithubTarget {
|
||||||
private final String username;
|
|
||||||
|
|
||||||
private final String repository;
|
private final String repository;
|
||||||
|
|
||||||
|
private final String username;
|
||||||
|
|
||||||
public GithubTarget(String username, String repository) {
|
public GithubTarget(String username, String repository) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepository() {
|
public String getRepository() {
|
||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,18 +16,16 @@ package code.name.monkey.retromusic.activities.saf;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import code.name.monkey.retromusic.R;
|
||||||
import com.heinrichreimersoftware.materialintro.app.IntroActivity;
|
import com.heinrichreimersoftware.materialintro.app.IntroActivity;
|
||||||
import com.heinrichreimersoftware.materialintro.slide.SimpleSlide;
|
import com.heinrichreimersoftware.materialintro.slide.SimpleSlide;
|
||||||
|
|
||||||
import code.name.monkey.retromusic.R;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hemanths on 2019-07-31.
|
* Created by hemanths on 2019-07-31.
|
||||||
*/
|
*/
|
||||||
public class SAFGuideActivity extends IntroActivity {
|
public class SAFGuideActivity extends IntroActivity {
|
||||||
|
|
||||||
public static final int REQUEST_CODE_SAF_GUIDE = 98;
|
public static final int REQUEST_CODE_SAF_GUIDE = 98;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -44,7 +42,8 @@ public class SAFGuideActivity extends IntroActivity {
|
||||||
|
|
||||||
addSlide(new SimpleSlide.Builder()
|
addSlide(new SimpleSlide.Builder()
|
||||||
.title(title)
|
.title(title)
|
||||||
.description(Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 ? R.string.saf_guide_slide1_description_before_o : R.string.saf_guide_slide1_description)
|
.description(Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
|
||||||
|
? R.string.saf_guide_slide1_description_before_o : R.string.saf_guide_slide1_description)
|
||||||
.image(R.drawable.saf_guide_1)
|
.image(R.drawable.saf_guide_1)
|
||||||
.background(R.color.md_deep_purple_300)
|
.background(R.color.md_deep_purple_300)
|
||||||
.backgroundDark(R.color.md_deep_purple_400)
|
.backgroundDark(R.color.md_deep_purple_400)
|
||||||
|
|
|
@ -1,416 +1,417 @@
|
||||||
package code.name.monkey.retromusic.activities.tageditor
|
package code.name.monkey.retromusic.activities.tageditor
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Activity
|
||||||
|
import android.app.SearchManager
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.*
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.*
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
import android.view.animation.OvershootInterpolator
|
import android.view.animation.OvershootInterpolator
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.*
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
|
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
|
import code.name.monkey.appthemehelper.util.TintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||||
import code.name.monkey.retromusic.activities.saf.SAFGuideActivity
|
import code.name.monkey.retromusic.activities.saf.SAFGuideActivity
|
||||||
import code.name.monkey.retromusic.util.*
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import com.afollestad.materialdialogs.*
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
|
import code.name.monkey.retromusic.util.SAFUtil
|
||||||
|
import com.afollestad.materialdialogs.LayoutMode
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||||
import com.afollestad.materialdialogs.list.listItems
|
import com.afollestad.materialdialogs.list.listItems
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import kotlinx.android.synthetic.main.activity_album_tag_editor.*
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.editorImage
|
||||||
import org.jaudiotagger.audio.*
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.imageContainer
|
||||||
|
import org.jaudiotagger.audio.AudioFile
|
||||||
|
import org.jaudiotagger.audio.AudioFileIO
|
||||||
import org.jaudiotagger.tag.FieldKey
|
import org.jaudiotagger.tag.FieldKey
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.Collections
|
||||||
|
|
||||||
abstract class AbsTagEditorActivity : AbsBaseActivity() {
|
abstract class AbsTagEditorActivity : AbsBaseActivity() {
|
||||||
|
|
||||||
protected var id: Int = 0
|
protected var id: Int = 0
|
||||||
private set
|
private set
|
||||||
private var paletteColorPrimary: Int = 0
|
private var paletteColorPrimary: Int = 0
|
||||||
private var isInNoImageMode: Boolean = false
|
private var isInNoImageMode: Boolean = false
|
||||||
private var songPaths: List<String>? = null
|
private var songPaths: List<String>? = null
|
||||||
lateinit var saveFab: MaterialButton
|
lateinit var saveFab: MaterialButton
|
||||||
|
|
||||||
private var savedSongPaths: List<String>? = null
|
private var savedSongPaths: List<String>? = null
|
||||||
private val currentSongPath: String? = null
|
private val currentSongPath: String? = null
|
||||||
private var savedTags: Map<FieldKey, String>? = null
|
private var savedTags: Map<FieldKey, String>? = null
|
||||||
private var savedArtworkInfo: ArtworkInfo? = null
|
private var savedArtworkInfo: ArtworkInfo? = null
|
||||||
|
|
||||||
protected val show: MaterialDialog
|
protected val show: MaterialDialog
|
||||||
get() = MaterialDialog(this, BottomSheet(LayoutMode.WRAP_CONTENT)).show {
|
get() = MaterialDialog(this, BottomSheet(LayoutMode.WRAP_CONTENT)).show {
|
||||||
cornerRadius(PreferenceUtil.getInstance(this@AbsTagEditorActivity).dialogCorner)
|
cornerRadius(PreferenceUtil.getInstance(this@AbsTagEditorActivity).dialogCorner)
|
||||||
title(R.string.update_image)
|
title(R.string.update_image)
|
||||||
listItems(items = items) { _, position, _ ->
|
listItems(items = items) { _, position, _ ->
|
||||||
when (position) {
|
when (position) {
|
||||||
0 -> startImagePicker()
|
0 -> startImagePicker()
|
||||||
1 -> searchImageOnWeb()
|
1 -> searchImageOnWeb()
|
||||||
2 -> deleteImage()
|
2 -> deleteImage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected abstract val contentViewLayout: Int
|
protected abstract val contentViewLayout: Int
|
||||||
|
|
||||||
internal val albumArtist: String?
|
internal val albumArtist: String?
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
protected val songTitle: String?
|
||||||
|
get() {
|
||||||
|
return try {
|
||||||
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TITLE)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected val composer: String?
|
||||||
|
get() {
|
||||||
|
return try {
|
||||||
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.COMPOSER)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected val songTitle: String?
|
protected val albumTitle: String?
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TITLE)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM)
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
protected val artistName: String?
|
||||||
protected val composer: String?
|
get() {
|
||||||
get() {
|
return try {
|
||||||
return try {
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ARTIST)
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.COMPOSER)
|
} catch (ignored: Exception) {
|
||||||
} catch (ignored: Exception) {
|
null
|
||||||
null
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
protected val albumArtistName: String?
|
||||||
|
get() {
|
||||||
|
return try {
|
||||||
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected val albumTitle: String?
|
protected val genreName: String?
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.GENRE)
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
protected val songYear: String?
|
||||||
|
get() {
|
||||||
|
return try {
|
||||||
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.YEAR)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected val artistName: String?
|
protected val trackNumber: String?
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ARTIST)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TRACK)
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
protected val lyrics: String?
|
||||||
|
get() {
|
||||||
|
return try {
|
||||||
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.LYRICS)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected val albumArtistName: String?
|
protected val albumArt: Bitmap?
|
||||||
get() {
|
get() {
|
||||||
return try {
|
try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
val artworkTag = getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.firstArtwork
|
||||||
} catch (ignored: Exception) {
|
if (artworkTag != null) {
|
||||||
null
|
val artworkBinaryData = artworkTag.binaryData
|
||||||
}
|
return BitmapFactory.decodeByteArray(
|
||||||
|
artworkBinaryData,
|
||||||
|
0,
|
||||||
|
artworkBinaryData.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(contentViewLayout)
|
||||||
|
|
||||||
protected val genreName: String?
|
saveFab = findViewById(R.id.saveTags)
|
||||||
get() {
|
getIntentExtras()
|
||||||
return try {
|
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.GENRE)
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
songPaths = getSongPaths()
|
||||||
|
if (songPaths!!.isEmpty()) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
protected val songYear: String?
|
setUpViews()
|
||||||
get() {
|
|
||||||
return try {
|
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.YEAR)
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected val trackNumber: String?
|
|
||||||
get() {
|
|
||||||
return try {
|
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TRACK)
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected val lyrics: String?
|
|
||||||
get() {
|
|
||||||
return try {
|
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.LYRICS)
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected val albumArt: Bitmap?
|
|
||||||
get() {
|
|
||||||
try {
|
|
||||||
val artworkTag = getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.firstArtwork
|
|
||||||
if (artworkTag != null) {
|
|
||||||
val artworkBinaryData = artworkTag.binaryData
|
|
||||||
return BitmapFactory.decodeByteArray(
|
|
||||||
artworkBinaryData,
|
|
||||||
0,
|
|
||||||
artworkBinaryData.size
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(contentViewLayout)
|
|
||||||
|
|
||||||
saveFab = findViewById(R.id.saveTags)
|
|
||||||
getIntentExtras()
|
|
||||||
|
|
||||||
songPaths = getSongPaths()
|
|
||||||
if (songPaths!!.isEmpty()) {
|
|
||||||
finish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setUpViews()
|
|
||||||
|
|
||||||
|
|
||||||
setNavigationbarColorAuto()
|
setNavigationbarColorAuto()
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpViews() {
|
private fun setUpViews() {
|
||||||
setUpScrollView()
|
setUpScrollView()
|
||||||
setUpFab()
|
setUpFab()
|
||||||
setUpImageView()
|
setUpImageView()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpScrollView() {
|
private fun setUpScrollView() {
|
||||||
//observableScrollView.setScrollViewCallbacks(observableScrollViewCallbacks);
|
//observableScrollView.setScrollViewCallbacks(observableScrollViewCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var items: List<String>
|
private lateinit var items: List<String>
|
||||||
|
|
||||||
private fun setUpImageView() {
|
private fun setUpImageView() {
|
||||||
loadCurrentImage()
|
loadCurrentImage()
|
||||||
items = listOf(
|
items = listOf(
|
||||||
getString(code.name.monkey.retromusic.R.string.pick_from_local_storage),
|
getString(code.name.monkey.retromusic.R.string.pick_from_local_storage),
|
||||||
getString(code.name.monkey.retromusic.R.string.web_search),
|
getString(code.name.monkey.retromusic.R.string.web_search),
|
||||||
getString(code.name.monkey.retromusic.R.string.remove_cover)
|
getString(code.name.monkey.retromusic.R.string.remove_cover)
|
||||||
)
|
)
|
||||||
editorImage?.setOnClickListener { show }
|
editorImage?.setOnClickListener { show }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startImagePicker() {
|
private fun startImagePicker() {
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||||
intent.type = "image/*"
|
intent.type = "image/*"
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
Intent.createChooser(
|
Intent.createChooser(
|
||||||
intent,
|
intent,
|
||||||
getString(code.name.monkey.retromusic.R.string.pick_from_local_storage)
|
getString(code.name.monkey.retromusic.R.string.pick_from_local_storage)
|
||||||
), REQUEST_CODE_SELECT_IMAGE
|
), REQUEST_CODE_SELECT_IMAGE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun loadCurrentImage()
|
protected abstract fun loadCurrentImage()
|
||||||
|
|
||||||
protected abstract fun searchImageOnWeb()
|
protected abstract fun searchImageOnWeb()
|
||||||
|
|
||||||
protected abstract fun deleteImage()
|
protected abstract fun deleteImage()
|
||||||
|
|
||||||
private fun setUpFab() {
|
private fun setUpFab() {
|
||||||
saveFab.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
saveFab.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
||||||
ColorStateList.valueOf(
|
ColorStateList.valueOf(
|
||||||
MaterialValueHelper.getPrimaryTextColor(
|
MaterialValueHelper.getPrimaryTextColor(
|
||||||
this,
|
this,
|
||||||
ColorUtil.isColorLight(
|
ColorUtil.isColorLight(
|
||||||
ThemeStore.accentColor(
|
ThemeStore.accentColor(
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).apply {
|
).apply {
|
||||||
saveFab.setTextColor(this)
|
saveFab.setTextColor(this)
|
||||||
saveFab.iconTint = this
|
saveFab.iconTint = this
|
||||||
}
|
}
|
||||||
saveFab.apply {
|
saveFab.apply {
|
||||||
scaleX = 0f
|
scaleX = 0f
|
||||||
scaleY = 0f
|
scaleY = 0f
|
||||||
isEnabled = false
|
isEnabled = false
|
||||||
setOnClickListener { save() }
|
setOnClickListener { save() }
|
||||||
TintHelper.setTintAuto(this, ThemeStore.accentColor(this@AbsTagEditorActivity), true)
|
TintHelper.setTintAuto(this, ThemeStore.accentColor(this@AbsTagEditorActivity), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun save()
|
protected abstract fun save()
|
||||||
|
|
||||||
private fun getIntentExtras() {
|
private fun getIntentExtras() {
|
||||||
val intentExtras = intent.extras
|
val intentExtras = intent.extras
|
||||||
if (intentExtras != null) {
|
if (intentExtras != null) {
|
||||||
id = intentExtras.getInt(EXTRA_ID)
|
id = intentExtras.getInt(EXTRA_ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun getSongPaths(): List<String>
|
protected abstract fun getSongPaths(): List<String>
|
||||||
|
|
||||||
protected fun searchWebFor(vararg keys: String) {
|
protected fun searchWebFor(vararg keys: String) {
|
||||||
val stringBuilder = StringBuilder()
|
val stringBuilder = StringBuilder()
|
||||||
for (key in keys) {
|
for (key in keys) {
|
||||||
stringBuilder.append(key)
|
stringBuilder.append(key)
|
||||||
stringBuilder.append(" ")
|
stringBuilder.append(" ")
|
||||||
}
|
}
|
||||||
val intent = Intent(Intent.ACTION_WEB_SEARCH)
|
val intent = Intent(Intent.ACTION_WEB_SEARCH)
|
||||||
intent.putExtra(SearchManager.QUERY, stringBuilder.toString())
|
intent.putExtra(SearchManager.QUERY, stringBuilder.toString())
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun setNoImageMode() {
|
protected fun setNoImageMode() {
|
||||||
isInNoImageMode = true
|
isInNoImageMode = true
|
||||||
imageContainer?.visibility = View.GONE
|
imageContainer?.visibility = View.GONE
|
||||||
editorImage?.visibility = View.GONE
|
editorImage?.visibility = View.GONE
|
||||||
editorImage?.isEnabled = false
|
editorImage?.isEnabled = false
|
||||||
|
|
||||||
setColors(
|
setColors(
|
||||||
intent.getIntExtra(
|
intent.getIntExtra(
|
||||||
EXTRA_PALETTE,
|
EXTRA_PALETTE,
|
||||||
ATHUtil.resolveColor(this, R.attr.colorPrimary)
|
ATHUtil.resolveColor(this, R.attr.colorPrimary)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun dataChanged() {
|
protected fun dataChanged() {
|
||||||
showFab()
|
showFab()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showFab() {
|
private fun showFab() {
|
||||||
saveFab.animate().setDuration(500).setInterpolator(OvershootInterpolator()).scaleX(1f)
|
saveFab.animate().setDuration(500).setInterpolator(OvershootInterpolator()).scaleX(1f)
|
||||||
.scaleY(1f).start()
|
.scaleY(1f).start()
|
||||||
saveFab.isEnabled = true
|
saveFab.isEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideFab() {
|
private fun hideFab() {
|
||||||
saveFab.animate().setDuration(500).setInterpolator(OvershootInterpolator()).scaleX(0.0f)
|
saveFab.animate().setDuration(500).setInterpolator(OvershootInterpolator()).scaleX(0.0f)
|
||||||
.scaleY(0.0f).start()
|
.scaleY(0.0f).start()
|
||||||
saveFab.isEnabled = false
|
saveFab.isEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun setImageBitmap(bitmap: Bitmap?, bgColor: Int) {
|
protected fun setImageBitmap(bitmap: Bitmap?, bgColor: Int) {
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
editorImage.setImageResource(code.name.monkey.retromusic.R.drawable.default_album_art)
|
editorImage.setImageResource(code.name.monkey.retromusic.R.drawable.default_album_art)
|
||||||
} else {
|
} else {
|
||||||
editorImage.setImageBitmap(bitmap)
|
editorImage.setImageBitmap(bitmap)
|
||||||
}
|
}
|
||||||
setColors(bgColor)
|
setColors(bgColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun setColors(color: Int) {
|
protected open fun setColors(color: Int) {
|
||||||
paletteColorPrimary = color
|
paletteColorPrimary = color
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun writeValuesToFiles(
|
protected fun writeValuesToFiles(
|
||||||
fieldKeyValueMap: Map<FieldKey, String>, artworkInfo: ArtworkInfo?
|
fieldKeyValueMap: Map<FieldKey, String>, artworkInfo: ArtworkInfo?
|
||||||
) {
|
) {
|
||||||
RetroUtil.hideSoftKeyboard(this)
|
RetroUtil.hideSoftKeyboard(this)
|
||||||
|
|
||||||
hideFab()
|
hideFab()
|
||||||
|
|
||||||
savedSongPaths = getSongPaths()
|
savedSongPaths = getSongPaths()
|
||||||
savedTags = fieldKeyValueMap
|
savedTags = fieldKeyValueMap
|
||||||
savedArtworkInfo = artworkInfo
|
savedArtworkInfo = artworkInfo
|
||||||
|
|
||||||
if (!SAFUtil.isSAFRequired(savedSongPaths)) {
|
if (!SAFUtil.isSAFRequired(savedSongPaths)) {
|
||||||
writeTags(savedSongPaths)
|
writeTags(savedSongPaths)
|
||||||
} else {
|
} else {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
if (SAFUtil.isSDCardAccessGranted(this)) {
|
if (SAFUtil.isSDCardAccessGranted(this)) {
|
||||||
writeTags(savedSongPaths)
|
writeTags(savedSongPaths)
|
||||||
} else {
|
} else {
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
Intent(this, SAFGuideActivity::class.java),
|
Intent(this, SAFGuideActivity::class.java),
|
||||||
SAFGuideActivity.REQUEST_CODE_SAF_GUIDE
|
SAFGuideActivity.REQUEST_CODE_SAF_GUIDE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun writeTags(paths: List<String>?) {
|
private fun writeTags(paths: List<String>?) {
|
||||||
WriteTagsAsyncTask(this).execute(
|
WriteTagsAsyncTask(this).execute(
|
||||||
WriteTagsAsyncTask.LoadingInfo(
|
WriteTagsAsyncTask.LoadingInfo(
|
||||||
paths,
|
paths,
|
||||||
savedTags,
|
savedTags,
|
||||||
savedArtworkInfo
|
savedArtworkInfo
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, intent)
|
super.onActivityResult(requestCode, resultCode, intent)
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
|
REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
|
||||||
intent?.data?.let {
|
intent?.data?.let {
|
||||||
loadImageFromFile(it)
|
loadImageFromFile(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SAFGuideActivity.REQUEST_CODE_SAF_GUIDE -> {
|
SAFGuideActivity.REQUEST_CODE_SAF_GUIDE -> {
|
||||||
SAFUtil.openTreePicker(this)
|
SAFUtil.openTreePicker(this)
|
||||||
}
|
}
|
||||||
SAFUtil.REQUEST_SAF_PICK_TREE -> {
|
SAFUtil.REQUEST_SAF_PICK_TREE -> {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
SAFUtil.saveTreeUri(this, intent)
|
SAFUtil.saveTreeUri(this, intent)
|
||||||
writeTags(savedSongPaths)
|
writeTags(savedSongPaths)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SAFUtil.REQUEST_SAF_PICK_FILE -> {
|
SAFUtil.REQUEST_SAF_PICK_FILE -> {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
writeTags(Collections.singletonList(currentSongPath + SAFUtil.SEPARATOR + intent!!.dataString))
|
writeTags(Collections.singletonList(currentSongPath + SAFUtil.SEPARATOR + intent!!.dataString))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun loadImageFromFile(selectedFile: Uri?)
|
protected abstract fun loadImageFromFile(selectedFile: Uri?)
|
||||||
|
|
||||||
private fun getAudioFile(path: String): AudioFile {
|
private fun getAudioFile(path: String): AudioFile {
|
||||||
return try {
|
return try {
|
||||||
AudioFileIO.read(File(path))
|
AudioFileIO.read(File(path))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Could not read audio file $path", e)
|
Log.e(TAG, "Could not read audio file $path", e)
|
||||||
AudioFile()
|
AudioFile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArtworkInfo constructor(val albumId: Int, val artwork: Bitmap?)
|
class ArtworkInfo constructor(val albumId: Int, val artwork: Bitmap?)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val EXTRA_ID = "extra_id"
|
const val EXTRA_ID = "extra_id"
|
||||||
const val EXTRA_PALETTE = "extra_palette"
|
const val EXTRA_PALETTE = "extra_palette"
|
||||||
private val TAG = AbsTagEditorActivity::class.java.simpleName
|
private val TAG = AbsTagEditorActivity::class.java.simpleName
|
||||||
private const val REQUEST_CODE_SELECT_IMAGE = 1000
|
private const val REQUEST_CODE_SELECT_IMAGE = 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,218 +31,230 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.bumptech.glide.request.animation.GlideAnimation
|
import com.bumptech.glide.request.animation.GlideAnimation
|
||||||
import com.bumptech.glide.request.target.SimpleTarget
|
import com.bumptech.glide.request.target.SimpleTarget
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import kotlinx.android.synthetic.main.activity_album_tag_editor.*
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.albumArtistContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.albumArtistText
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.albumText
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.albumTitleContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.genreContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.genreTitle
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.toolbar
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.yearContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_album_tag_editor.yearTitle
|
||||||
import org.jaudiotagger.tag.FieldKey
|
import org.jaudiotagger.tag.FieldKey
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
|
import java.util.EnumMap
|
||||||
|
|
||||||
class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
||||||
override val contentViewLayout: Int
|
override val contentViewLayout: Int
|
||||||
get() = R.layout.activity_album_tag_editor
|
get() = R.layout.activity_album_tag_editor
|
||||||
|
|
||||||
override fun loadImageFromFile(selectedFileUri: Uri?) {
|
override fun loadImageFromFile(selectedFileUri: Uri?) {
|
||||||
|
|
||||||
Glide.with(this@AlbumTagEditorActivity).load(selectedFileUri).asBitmap()
|
Glide.with(this@AlbumTagEditorActivity).load(selectedFileUri).asBitmap()
|
||||||
.transcode(BitmapPaletteTranscoder(this), BitmapPaletteWrapper::class.java)
|
.transcode(BitmapPaletteTranscoder(this), BitmapPaletteWrapper::class.java)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)
|
.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)
|
||||||
.into(object : SimpleTarget<BitmapPaletteWrapper>() {
|
.into(object : SimpleTarget<BitmapPaletteWrapper>() {
|
||||||
override fun onResourceReady(
|
override fun onResourceReady(
|
||||||
resource: BitmapPaletteWrapper?,
|
resource: BitmapPaletteWrapper?,
|
||||||
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>?
|
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>?
|
||||||
) {
|
) {
|
||||||
getColor(resource?.palette, Color.TRANSPARENT)
|
getColor(resource?.palette, Color.TRANSPARENT)
|
||||||
albumArtBitmap = resource?.bitmap?.let { ImageUtil.resizeBitmap(it, 2048) }
|
albumArtBitmap = resource?.bitmap?.let { ImageUtil.resizeBitmap(it, 2048) }
|
||||||
setImageBitmap(albumArtBitmap, getColor(resource?.palette, ATHUtil.resolveColor(this@AlbumTagEditorActivity, R.attr.defaultFooterColor)))
|
setImageBitmap(
|
||||||
deleteAlbumArt = false
|
albumArtBitmap,
|
||||||
dataChanged()
|
getColor(
|
||||||
setResult(Activity.RESULT_OK)
|
resource?.palette,
|
||||||
}
|
ATHUtil.resolveColor(this@AlbumTagEditorActivity, R.attr.defaultFooterColor)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
deleteAlbumArt = false
|
||||||
|
dataChanged()
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
||||||
super.onLoadFailed(e, errorDrawable)
|
super.onLoadFailed(e, errorDrawable)
|
||||||
Toast.makeText(this@AlbumTagEditorActivity, e.toString(), Toast.LENGTH_LONG)
|
Toast.makeText(this@AlbumTagEditorActivity, e.toString(), Toast.LENGTH_LONG)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private var albumArtBitmap: Bitmap? = null
|
private var albumArtBitmap: Bitmap? = null
|
||||||
private var deleteAlbumArt: Boolean = false
|
private var deleteAlbumArt: Boolean = false
|
||||||
private var lastFMRestClient: LastFMRestClient? = null
|
private var lastFMRestClient: LastFMRestClient? = null
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
applyToolbar(toolbar)
|
applyToolbar(toolbar)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
setDrawUnderStatusBar()
|
setDrawUnderStatusBar()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
lastFMRestClient = LastFMRestClient(this)
|
lastFMRestClient = LastFMRestClient(this)
|
||||||
|
|
||||||
setUpViews()
|
setUpViews()
|
||||||
setupToolbar()
|
setupToolbar()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpViews() {
|
private fun setUpViews() {
|
||||||
fillViewsWithFileTags()
|
fillViewsWithFileTags()
|
||||||
|
|
||||||
MaterialUtil.setTint(yearContainer, false)
|
MaterialUtil.setTint(yearContainer, false)
|
||||||
MaterialUtil.setTint(genreContainer, false)
|
MaterialUtil.setTint(genreContainer, false)
|
||||||
MaterialUtil.setTint(albumTitleContainer, false)
|
MaterialUtil.setTint(albumTitleContainer, false)
|
||||||
MaterialUtil.setTint(albumArtistContainer, false)
|
MaterialUtil.setTint(albumArtistContainer, false)
|
||||||
|
|
||||||
albumText.appHandleColor().addTextChangedListener(this)
|
albumText.appHandleColor().addTextChangedListener(this)
|
||||||
albumArtistText.appHandleColor().addTextChangedListener(this)
|
albumArtistText.appHandleColor().addTextChangedListener(this)
|
||||||
genreTitle.appHandleColor().addTextChangedListener(this)
|
genreTitle.appHandleColor().addTextChangedListener(this)
|
||||||
yearTitle.appHandleColor().addTextChangedListener(this)
|
yearTitle.appHandleColor().addTextChangedListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillViewsWithFileTags() {
|
private fun fillViewsWithFileTags() {
|
||||||
albumText.setText(albumTitle)
|
albumText.setText(albumTitle)
|
||||||
albumArtistText.setText(albumArtistName)
|
albumArtistText.setText(albumArtistName)
|
||||||
genreTitle.setText(genreName)
|
genreTitle.setText(genreName)
|
||||||
yearTitle.setText(songYear)
|
yearTitle.setText(songYear)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadCurrentImage() {
|
override fun loadCurrentImage() {
|
||||||
val bitmap = albumArt
|
val bitmap = albumArt
|
||||||
setImageBitmap(
|
setImageBitmap(
|
||||||
bitmap,
|
bitmap,
|
||||||
getColor(
|
getColor(
|
||||||
generatePalette(bitmap),
|
generatePalette(bitmap),
|
||||||
ATHUtil.resolveColor(this, R.attr.defaultFooterColor)
|
ATHUtil.resolveColor(this, R.attr.defaultFooterColor)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
deleteAlbumArt = false
|
deleteAlbumArt = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractDetails(lastFmAlbum: LastFmAlbum) {
|
private fun extractDetails(lastFmAlbum: LastFmAlbum) {
|
||||||
if (lastFmAlbum.album != null) {
|
if (lastFmAlbum.album != null) {
|
||||||
|
|
||||||
val url = LastFMUtil.getLargestAlbumImageUrl(lastFmAlbum.album.image)
|
val url = LastFMUtil.getLargestAlbumImageUrl(lastFmAlbum.album.image)
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(url) && url.trim { it <= ' ' }.isNotEmpty()) {
|
if (!TextUtils.isEmpty(url) && url.trim { it <= ' ' }.isNotEmpty()) {
|
||||||
Glide.with(this@AlbumTagEditorActivity).load(url).asBitmap()
|
Glide.with(this@AlbumTagEditorActivity).load(url).asBitmap()
|
||||||
.transcode(BitmapPaletteTranscoder(this), BitmapPaletteWrapper::class.java)
|
.transcode(BitmapPaletteTranscoder(this), BitmapPaletteWrapper::class.java)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.SOURCE).error(R.drawable.default_album_art)
|
.diskCacheStrategy(DiskCacheStrategy.SOURCE).error(R.drawable.default_album_art)
|
||||||
.into(object : SimpleTarget<BitmapPaletteWrapper>() {
|
.into(object : SimpleTarget<BitmapPaletteWrapper>() {
|
||||||
override fun onLoadFailed(
|
override fun onLoadFailed(
|
||||||
e: java.lang.Exception?,
|
e: java.lang.Exception?,
|
||||||
errorDrawable: Drawable?
|
errorDrawable: Drawable?
|
||||||
) {
|
) {
|
||||||
super.onLoadFailed(e, errorDrawable)
|
super.onLoadFailed(e, errorDrawable)
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this@AlbumTagEditorActivity,
|
this@AlbumTagEditorActivity,
|
||||||
e.toString(),
|
e.toString(),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceReady(
|
override fun onResourceReady(
|
||||||
resource: BitmapPaletteWrapper?,
|
resource: BitmapPaletteWrapper?,
|
||||||
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>?
|
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>?
|
||||||
) {
|
) {
|
||||||
albumArtBitmap = resource?.bitmap?.let {
|
albumArtBitmap = resource?.bitmap?.let {
|
||||||
ImageUtil.resizeBitmap(
|
ImageUtil.resizeBitmap(
|
||||||
it,
|
it,
|
||||||
2048
|
2048
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
setImageBitmap(
|
setImageBitmap(
|
||||||
albumArtBitmap,
|
albumArtBitmap,
|
||||||
getColor(
|
getColor(
|
||||||
resource?.palette,
|
resource?.palette,
|
||||||
ATHUtil.resolveColor(
|
ATHUtil.resolveColor(
|
||||||
this@AlbumTagEditorActivity,
|
this@AlbumTagEditorActivity,
|
||||||
R.attr.defaultFooterColor
|
R.attr.defaultFooterColor
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
deleteAlbumArt = false
|
deleteAlbumArt = false
|
||||||
dataChanged()
|
dataChanged()
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (lastFmAlbum.album.tags.tag.size > 0) {
|
if (lastFmAlbum.album.tags.tag.size > 0) {
|
||||||
genreTitle.setText(lastFmAlbum.album.tags.tag[0].name)
|
genreTitle.setText(lastFmAlbum.album.tags.tag[0].name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
toastLoadingFailed()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
private fun toastLoadingFailed() {
|
||||||
toastLoadingFailed()
|
Toast.makeText(
|
||||||
}
|
this@AlbumTagEditorActivity,
|
||||||
|
R.string.could_not_download_album_cover,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
private fun toastLoadingFailed() {
|
override fun searchImageOnWeb() {
|
||||||
Toast.makeText(
|
searchWebFor(albumText.text.toString(), albumArtistText.text.toString())
|
||||||
this@AlbumTagEditorActivity,
|
}
|
||||||
R.string.could_not_download_album_cover,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchImageOnWeb() {
|
override fun deleteImage() {
|
||||||
searchWebFor(albumText.text.toString(), albumArtistText.text.toString())
|
setImageBitmap(
|
||||||
}
|
BitmapFactory.decodeResource(resources, R.drawable.default_album_art),
|
||||||
|
ATHUtil.resolveColor(this, R.attr.defaultFooterColor)
|
||||||
|
)
|
||||||
|
deleteAlbumArt = true
|
||||||
|
dataChanged()
|
||||||
|
}
|
||||||
|
|
||||||
override fun deleteImage() {
|
override fun save() {
|
||||||
setImageBitmap(
|
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
||||||
BitmapFactory.decodeResource(resources, R.drawable.default_album_art),
|
fieldKeyValueMap[FieldKey.ALBUM] = albumText.text.toString()
|
||||||
ATHUtil.resolveColor(this, R.attr.defaultFooterColor)
|
//android seems not to recognize album_artist field so we additionally write the normal artist field
|
||||||
)
|
fieldKeyValueMap[FieldKey.ARTIST] = albumArtistText.text.toString()
|
||||||
deleteAlbumArt = true
|
fieldKeyValueMap[FieldKey.ALBUM_ARTIST] = albumArtistText.text.toString()
|
||||||
dataChanged()
|
fieldKeyValueMap[FieldKey.GENRE] = genreTitle.text.toString()
|
||||||
}
|
fieldKeyValueMap[FieldKey.YEAR] = yearTitle.text.toString()
|
||||||
|
|
||||||
override fun save() {
|
writeValuesToFiles(
|
||||||
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
fieldKeyValueMap, if (deleteAlbumArt) ArtworkInfo(id, null)
|
||||||
fieldKeyValueMap[FieldKey.ALBUM] = albumText.text.toString()
|
else if (albumArtBitmap == null) null else ArtworkInfo(id, albumArtBitmap!!)
|
||||||
//android seems not to recognize album_artist field so we additionally write the normal artist field
|
)
|
||||||
fieldKeyValueMap[FieldKey.ARTIST] = albumArtistText.text.toString()
|
}
|
||||||
fieldKeyValueMap[FieldKey.ALBUM_ARTIST] = albumArtistText.text.toString()
|
|
||||||
fieldKeyValueMap[FieldKey.GENRE] = genreTitle.text.toString()
|
|
||||||
fieldKeyValueMap[FieldKey.YEAR] = yearTitle.text.toString()
|
|
||||||
|
|
||||||
writeValuesToFiles(
|
override fun getSongPaths(): List<String> {
|
||||||
fieldKeyValueMap, if (deleteAlbumArt) ArtworkInfo(id, null)
|
val songs = AlbumLoader.getAlbum(this, id).songs
|
||||||
else if (albumArtBitmap == null) null else ArtworkInfo(id, albumArtBitmap!!)
|
val paths = ArrayList<String>(songs!!.size)
|
||||||
)
|
for (song in songs) {
|
||||||
}
|
paths.add(song.data)
|
||||||
|
}
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
override fun getSongPaths(): List<String> {
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
||||||
val songs = AlbumLoader.getAlbum(this, id).songs
|
}
|
||||||
val paths = ArrayList<String>(songs!!.size)
|
|
||||||
for (song in songs) {
|
|
||||||
paths.add(song.data)
|
|
||||||
}
|
|
||||||
return paths
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
override fun afterTextChanged(s: Editable) {
|
||||||
|
dataChanged()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
override fun setColors(color: Int) {
|
||||||
|
super.setColors(color)
|
||||||
|
saveFab.backgroundTintList = ColorStateList.valueOf(color)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
companion object {
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable) {
|
val TAG: String = AlbumTagEditorActivity::class.java.simpleName
|
||||||
dataChanged()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun setColors(color: Int) {
|
|
||||||
super.setColors(color)
|
|
||||||
saveFab.backgroundTintList = ColorStateList.valueOf(color)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
val TAG: String = AlbumTagEditorActivity::class.java.simpleName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,16 +9,34 @@ import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.extensions.appHandleColor
|
import code.name.monkey.retromusic.extensions.appHandleColor
|
||||||
import code.name.monkey.retromusic.extensions.applyToolbar
|
import code.name.monkey.retromusic.extensions.applyToolbar
|
||||||
import code.name.monkey.retromusic.loaders.SongLoader
|
import code.name.monkey.retromusic.loaders.SongLoader
|
||||||
import kotlinx.android.synthetic.main.activity_song_tag_editor.*
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.albumArtistContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.albumArtistText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.albumText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.albumTextContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.artistContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.artistText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.composerContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.genreContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.genreText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.lyricsContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.lyricsText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.songComposerText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.songText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.songTextContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.toolbar
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.trackNumberContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.trackNumberText
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.yearContainer
|
||||||
|
import kotlinx.android.synthetic.main.activity_song_tag_editor.yearText
|
||||||
import org.jaudiotagger.tag.FieldKey
|
import org.jaudiotagger.tag.FieldKey
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
|
import java.util.EnumMap
|
||||||
|
|
||||||
class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
||||||
|
|
||||||
override val contentViewLayout: Int
|
override val contentViewLayout: Int
|
||||||
get() = R.layout.activity_song_tag_editor
|
get() = R.layout.activity_song_tag_editor
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
@ -64,15 +82,12 @@ class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadCurrentImage() {
|
override fun loadCurrentImage() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchImageOnWeb() {
|
override fun searchImageOnWeb() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteImage() {
|
override fun deleteImage() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun save() {
|
override fun save() {
|
||||||
|
@ -96,15 +111,12 @@ class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadImageFromFile(selectedFile: Uri?) {
|
override fun loadImageFromFile(selectedFile: Uri?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
|
|
|
@ -7,19 +7,14 @@ import android.graphics.Bitmap;
|
||||||
import android.media.MediaScannerConnection;
|
import android.media.MediaScannerConnection;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import code.name.monkey.retromusic.R;
|
||||||
|
import code.name.monkey.retromusic.misc.DialogAsyncTask;
|
||||||
|
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
|
||||||
|
import code.name.monkey.retromusic.util.MusicUtil;
|
||||||
|
import code.name.monkey.retromusic.util.SAFUtil;
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
import org.jaudiotagger.audio.AudioFile;
|
|
||||||
import org.jaudiotagger.audio.AudioFileIO;
|
|
||||||
import org.jaudiotagger.tag.FieldKey;
|
|
||||||
import org.jaudiotagger.tag.Tag;
|
|
||||||
import org.jaudiotagger.tag.images.Artwork;
|
|
||||||
import org.jaudiotagger.tag.images.ArtworkFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -27,16 +22,35 @@ import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.jaudiotagger.audio.AudioFile;
|
||||||
import code.name.monkey.retromusic.R;
|
import org.jaudiotagger.audio.AudioFileIO;
|
||||||
import code.name.monkey.retromusic.misc.DialogAsyncTask;
|
import org.jaudiotagger.tag.FieldKey;
|
||||||
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
|
import org.jaudiotagger.tag.Tag;
|
||||||
import code.name.monkey.retromusic.util.MusicUtil;
|
import org.jaudiotagger.tag.images.Artwork;
|
||||||
import code.name.monkey.retromusic.util.SAFUtil;
|
import org.jaudiotagger.tag.images.ArtworkFactory;
|
||||||
|
|
||||||
public class WriteTagsAsyncTask extends
|
public class WriteTagsAsyncTask extends
|
||||||
DialogAsyncTask<WriteTagsAsyncTask.LoadingInfo, Integer, String[]> {
|
DialogAsyncTask<WriteTagsAsyncTask.LoadingInfo, Integer, String[]> {
|
||||||
|
|
||||||
|
public static class LoadingInfo {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
final Map<FieldKey, String> fieldKeyValueMap;
|
||||||
|
|
||||||
|
final Collection<String> filePaths;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private AbsTagEditorActivity.ArtworkInfo artworkInfo;
|
||||||
|
|
||||||
|
public LoadingInfo(Collection<String> filePaths,
|
||||||
|
@Nullable Map<FieldKey, String> fieldKeyValueMap,
|
||||||
|
@Nullable AbsTagEditorActivity.ArtworkInfo artworkInfo) {
|
||||||
|
this.filePaths = filePaths;
|
||||||
|
this.fieldKeyValueMap = fieldKeyValueMap;
|
||||||
|
this.artworkInfo = artworkInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private WeakReference<Activity> activity;
|
private WeakReference<Activity> activity;
|
||||||
|
|
||||||
public WriteTagsAsyncTask(@NonNull Activity activity) {
|
public WriteTagsAsyncTask(@NonNull Activity activity) {
|
||||||
|
@ -44,6 +58,16 @@ public class WriteTagsAsyncTask extends
|
||||||
this.activity = new WeakReference<>(activity);
|
this.activity = new WeakReference<>(activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
protected Dialog createDialog(@NonNull Context context) {
|
||||||
|
return new MaterialAlertDialogBuilder(context)
|
||||||
|
.setTitle(R.string.saving_changes)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setView(R.layout.loading)
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String[] doInBackground(LoadingInfo... params) {
|
protected String[] doInBackground(LoadingInfo... params) {
|
||||||
try {
|
try {
|
||||||
|
@ -120,8 +144,9 @@ public class WriteTagsAsyncTask extends
|
||||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
|
||||||
paths = new ArrayList<>(info.filePaths.size());
|
paths = new ArrayList<>(info.filePaths.size());
|
||||||
for (String path : info.filePaths) {
|
for (String path : info.filePaths) {
|
||||||
if (path.contains(SAFUtil.SEPARATOR))
|
if (path.contains(SAFUtil.SEPARATOR)) {
|
||||||
path = path.split(SAFUtil.SEPARATOR)[0];
|
path = path.split(SAFUtil.SEPARATOR)[0];
|
||||||
|
}
|
||||||
paths.add(path);
|
paths.add(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,33 +158,16 @@ public class WriteTagsAsyncTask extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(String[] toBeScanned) {
|
|
||||||
super.onPostExecute(toBeScanned);
|
|
||||||
scan(toBeScanned);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCancelled(String[] toBeScanned) {
|
protected void onCancelled(String[] toBeScanned) {
|
||||||
super.onCancelled(toBeScanned);
|
super.onCancelled(toBeScanned);
|
||||||
scan(toBeScanned);
|
scan(toBeScanned);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scan(String[] toBeScanned) {
|
|
||||||
Activity activity = this.activity.get();
|
|
||||||
if (activity != null) {
|
|
||||||
MediaScannerConnection.scanFile(activity, toBeScanned, null, new UpdateToastMediaScannerCompletionListener(activity, toBeScanned));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
@Override
|
||||||
protected Dialog createDialog(@NonNull Context context) {
|
protected void onPostExecute(String[] toBeScanned) {
|
||||||
return new MaterialAlertDialogBuilder(context)
|
super.onPostExecute(toBeScanned);
|
||||||
.setTitle(R.string.saving_changes)
|
scan(toBeScanned);
|
||||||
.setCancelable(false)
|
|
||||||
.setView(R.layout.loading)
|
|
||||||
.create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -169,20 +177,11 @@ public class WriteTagsAsyncTask extends
|
||||||
//((MaterialDialog) dialog).setProgress(values[0]);
|
//((MaterialDialog) dialog).setProgress(values[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LoadingInfo {
|
private void scan(String[] toBeScanned) {
|
||||||
|
Activity activity = this.activity.get();
|
||||||
final Collection<String> filePaths;
|
if (activity != null) {
|
||||||
@Nullable
|
MediaScannerConnection.scanFile(activity, toBeScanned, null,
|
||||||
final Map<FieldKey, String> fieldKeyValueMap;
|
new UpdateToastMediaScannerCompletionListener(activity, toBeScanned));
|
||||||
@Nullable
|
|
||||||
private AbsTagEditorActivity.ArtworkInfo artworkInfo;
|
|
||||||
|
|
||||||
public LoadingInfo(Collection<String> filePaths,
|
|
||||||
@Nullable Map<FieldKey, String> fieldKeyValueMap,
|
|
||||||
@Nullable AbsTagEditorActivity.ArtworkInfo artworkInfo) {
|
|
||||||
this.filePaths = filePaths;
|
|
||||||
this.fieldKeyValueMap = fieldKeyValueMap;
|
|
||||||
this.artworkInfo = artworkInfo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,8 +15,11 @@
|
||||||
package code.name.monkey.retromusic.appwidgets
|
package code.name.monkey.retromusic.appwidgets
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.*
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -28,203 +31,208 @@ import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget
|
||||||
import code.name.monkey.retromusic.glide.SongGlideRequest
|
import code.name.monkey.retromusic.glide.SongGlideRequest
|
||||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||||
import code.name.monkey.retromusic.service.MusicService
|
import code.name.monkey.retromusic.service.MusicService
|
||||||
import code.name.monkey.retromusic.service.MusicService.*
|
import code.name.monkey.retromusic.service.MusicService.ACTION_REWIND
|
||||||
import code.name.monkey.retromusic.util.*
|
import code.name.monkey.retromusic.service.MusicService.ACTION_SKIP
|
||||||
|
import code.name.monkey.retromusic.service.MusicService.ACTION_TOGGLE_PAUSE
|
||||||
|
import code.name.monkey.retromusic.util.ImageUtil
|
||||||
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.animation.GlideAnimation
|
import com.bumptech.glide.request.animation.GlideAnimation
|
||||||
import com.bumptech.glide.request.target.*
|
import com.bumptech.glide.request.target.SimpleTarget
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
|
|
||||||
class AppWidgetClassic : BaseAppWidget() {
|
class AppWidgetClassic : BaseAppWidget() {
|
||||||
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
|
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize given widgets to default state, where we launch Music on default click and hide
|
* Initialize given widgets to default state, where we launch Music on default click and hide
|
||||||
* actions if service not running.
|
* actions if service not running.
|
||||||
*/
|
*/
|
||||||
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
|
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
|
||||||
val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_classic)
|
val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_classic)
|
||||||
|
|
||||||
|
|
||||||
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
||||||
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
|
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
|
||||||
appWidgetView.setImageViewBitmap(
|
appWidgetView.setImageViewBitmap(
|
||||||
R.id.button_next, createBitmap(
|
R.id.button_next,
|
||||||
RetroUtil.getTintedVectorDrawable(
|
createBitmap(
|
||||||
context,
|
RetroUtil.getTintedVectorDrawable(
|
||||||
R.drawable.ic_skip_next_white_24dp,
|
context,
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
R.drawable.ic_skip_next_white_24dp,
|
||||||
context, true
|
MaterialValueHelper.getSecondaryTextColor(context, true)
|
||||||
)
|
)!!, 1f
|
||||||
)!!, 1f
|
)
|
||||||
)
|
)
|
||||||
)
|
appWidgetView.setImageViewBitmap(
|
||||||
appWidgetView.setImageViewBitmap(
|
R.id.button_prev,
|
||||||
R.id.button_prev, createBitmap(
|
createBitmap(
|
||||||
RetroUtil.getTintedVectorDrawable(
|
RetroUtil.getTintedVectorDrawable(
|
||||||
context,
|
context,
|
||||||
R.drawable.ic_skip_previous_white_24dp,
|
R.drawable.ic_skip_previous_white_24dp,
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
MaterialValueHelper.getSecondaryTextColor(context, true)
|
||||||
context, true
|
)!!, 1f
|
||||||
)
|
)
|
||||||
)!!, 1f
|
)
|
||||||
)
|
appWidgetView.setImageViewBitmap(
|
||||||
)
|
R.id.button_toggle_play_pause,
|
||||||
appWidgetView.setImageViewBitmap(
|
createBitmap(
|
||||||
R.id.button_toggle_play_pause, createBitmap(
|
RetroUtil.getTintedVectorDrawable(
|
||||||
RetroUtil.getTintedVectorDrawable(
|
context,
|
||||||
context,
|
R.drawable.ic_play_arrow_white_32dp,
|
||||||
R.drawable.ic_play_arrow_white_32dp,
|
MaterialValueHelper.getSecondaryTextColor(context, true)
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
)!!, 1f
|
||||||
context, true
|
)
|
||||||
)
|
)
|
||||||
)!!, 1f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
linkButtons(context, appWidgetView)
|
linkButtons(context, appWidgetView)
|
||||||
pushUpdate(context, appWidgetIds, appWidgetView)
|
pushUpdate(context, appWidgetIds, appWidgetView)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update all active widget instances by pushing changes
|
* Update all active widget instances by pushing changes
|
||||||
*/
|
*/
|
||||||
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
|
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
|
||||||
val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_classic)
|
val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_classic)
|
||||||
|
|
||||||
val isPlaying = service.isPlaying
|
val isPlaying = service.isPlaying
|
||||||
val song = service.currentSong
|
val song = service.currentSong
|
||||||
|
|
||||||
// Set the titles and artwork
|
// Set the titles and artwork
|
||||||
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
|
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
|
||||||
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
||||||
} else {
|
} else {
|
||||||
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
|
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
|
||||||
appWidgetView.setTextViewText(R.id.title, song.title)
|
appWidgetView.setTextViewText(R.id.title, song.title)
|
||||||
appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song))
|
appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link actions buttons to intents
|
// Link actions buttons to intents
|
||||||
linkButtons(service, appWidgetView)
|
linkButtons(service, appWidgetView)
|
||||||
|
|
||||||
if (imageSize == 0) {
|
if (imageSize == 0) {
|
||||||
imageSize = service.resources.getDimensionPixelSize(R.dimen.app_widget_classic_image_size)
|
imageSize = service.resources.getDimensionPixelSize(R.dimen.app_widget_classic_image_size)
|
||||||
}
|
}
|
||||||
if (cardRadius == 0f) {
|
if (cardRadius == 0f) {
|
||||||
cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius)
|
cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the album cover async and push the update on completion
|
// Load the album cover async and push the update on completion
|
||||||
val appContext = service.applicationContext
|
val appContext = service.applicationContext
|
||||||
service.runOnUiThread {
|
service.runOnUiThread {
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
Glide.clear(target)
|
Glide.clear(target)
|
||||||
}
|
}
|
||||||
target = SongGlideRequest.Builder.from(Glide.with(service), song)
|
target = SongGlideRequest.Builder.from(Glide.with(service), song)
|
||||||
.checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop()
|
.checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop()
|
||||||
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
|
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
|
||||||
override fun onResourceReady(
|
override fun onResourceReady(
|
||||||
resource: BitmapPaletteWrapper,
|
resource: BitmapPaletteWrapper,
|
||||||
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>
|
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>
|
||||||
) {
|
) {
|
||||||
val palette = resource.palette
|
val palette = resource.palette
|
||||||
update(
|
update(
|
||||||
resource.bitmap, palette.getVibrantColor(
|
resource.bitmap,
|
||||||
palette.getMutedColor(
|
palette.getVibrantColor(
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
palette.getMutedColor(
|
||||||
service, true
|
MaterialValueHelper.getSecondaryTextColor(
|
||||||
)
|
service,
|
||||||
)
|
true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
||||||
super.onLoadFailed(e, errorDrawable)
|
super.onLoadFailed(e, errorDrawable)
|
||||||
update(null, MaterialValueHelper.getSecondaryTextColor(service, true))
|
update(null, Color.WHITE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun update(bitmap: Bitmap?, color: Int) {
|
private fun update(bitmap: Bitmap?, color: Int) {
|
||||||
// Set correct drawable for pause state
|
// Set correct drawable for pause state
|
||||||
val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_24dp
|
val playPauseRes =
|
||||||
appWidgetView.setImageViewBitmap(
|
if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_24dp
|
||||||
R.id.button_toggle_play_pause, ImageUtil.createBitmap(
|
appWidgetView.setImageViewBitmap(
|
||||||
ImageUtil.getTintedVectorDrawable(
|
R.id.button_toggle_play_pause,
|
||||||
service, playPauseRes, color
|
ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(service, playPauseRes, color))
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set prev/next button drawables
|
// Set prev/next button drawables
|
||||||
appWidgetView.setImageViewBitmap(
|
appWidgetView.setImageViewBitmap(
|
||||||
R.id.button_next, ImageUtil.createBitmap(
|
R.id.button_next,
|
||||||
ImageUtil.getTintedVectorDrawable(
|
ImageUtil.createBitmap(
|
||||||
service, R.drawable.ic_skip_next_white_24dp, color
|
ImageUtil.getTintedVectorDrawable(
|
||||||
)
|
service,
|
||||||
)
|
R.drawable.ic_skip_next_white_24dp,
|
||||||
)
|
color
|
||||||
appWidgetView.setImageViewBitmap(
|
)
|
||||||
R.id.button_prev, ImageUtil.createBitmap(
|
)
|
||||||
ImageUtil.getTintedVectorDrawable(
|
)
|
||||||
service, R.drawable.ic_skip_previous_white_24dp, color
|
appWidgetView.setImageViewBitmap(
|
||||||
)
|
R.id.button_prev,
|
||||||
)
|
ImageUtil.createBitmap(
|
||||||
)
|
ImageUtil.getTintedVectorDrawable(
|
||||||
|
service,
|
||||||
|
R.drawable.ic_skip_previous_white_24dp,
|
||||||
|
color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val image = getAlbumArtDrawable(service.resources, bitmap)
|
val image = getAlbumArtDrawable(service.resources, bitmap)
|
||||||
val roundedBitmap = createRoundedBitmap(
|
val roundedBitmap =
|
||||||
image, imageSize, imageSize, cardRadius, 0F, cardRadius, 0F
|
createRoundedBitmap(image, imageSize, imageSize, cardRadius, 0F, cardRadius, 0F)
|
||||||
)
|
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
||||||
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
|
||||||
|
|
||||||
pushUpdate(appContext, appWidgetIds, appWidgetView)
|
pushUpdate(appContext, appWidgetIds, appWidgetView)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link up various button actions using [PendingIntent].
|
* Link up various button actions using [PendingIntent].
|
||||||
*/
|
*/
|
||||||
private fun linkButtons(context: Context, views: RemoteViews) {
|
private fun linkButtons(context: Context, views: RemoteViews) {
|
||||||
val action = Intent(context, MainActivity::class.java).putExtra("expand", true)
|
val action = Intent(context, MainActivity::class.java).putExtra("expand", true)
|
||||||
var pendingIntent: PendingIntent
|
var pendingIntent: PendingIntent
|
||||||
|
|
||||||
val serviceName = ComponentName(context, MusicService::class.java)
|
val serviceName = ComponentName(context, MusicService::class.java)
|
||||||
|
|
||||||
// Home
|
// Home
|
||||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
|
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
|
||||||
views.setOnClickPendingIntent(R.id.image, pendingIntent)
|
views.setOnClickPendingIntent(R.id.image, pendingIntent)
|
||||||
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
|
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
|
||||||
|
|
||||||
// Previous track
|
// Previous track
|
||||||
pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName)
|
||||||
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
|
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
|
||||||
|
|
||||||
// Play and pause
|
// Play and pause
|
||||||
pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName)
|
||||||
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
|
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
|
||||||
|
|
||||||
// Next track
|
// Next track
|
||||||
pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName)
|
||||||
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
|
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val NAME = "app_widget_classic"
|
const val NAME = "app_widget_classic"
|
||||||
|
|
||||||
private var mInstance: AppWidgetClassic? = null
|
private var mInstance: AppWidgetClassic? = null
|
||||||
private var imageSize = 0
|
private var imageSize = 0
|
||||||
private var cardRadius = 0f
|
private var cardRadius = 0f
|
||||||
|
|
||||||
val instance: AppWidgetClassic
|
val instance: AppWidgetClassic
|
||||||
@Synchronized get() {
|
@Synchronized get() {
|
||||||
if (mInstance == null) {
|
if (mInstance == null) {
|
||||||
mInstance = AppWidgetClassic()
|
mInstance = AppWidgetClassic()
|
||||||
}
|
}
|
||||||
return mInstance!!
|
return mInstance!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
package code.name.monkey.retromusic.appwidgets
|
package code.name.monkey.retromusic.appwidgets
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.*
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
@ -32,207 +34,175 @@ import code.name.monkey.retromusic.service.MusicService.*
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.animation.GlideAnimation
|
import com.bumptech.glide.request.animation.GlideAnimation
|
||||||
import com.bumptech.glide.request.target.*
|
import com.bumptech.glide.request.target.SimpleTarget
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
|
|
||||||
class AppWidgetSmall : BaseAppWidget() {
|
class AppWidgetSmall : BaseAppWidget() {
|
||||||
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
|
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize given widgets to default state, where we launch Music on default click and hide
|
* Initialize given widgets to default state, where we launch Music on default click and hide
|
||||||
* actions if service not running.
|
* actions if service not running.
|
||||||
*/
|
*/
|
||||||
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
|
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
|
||||||
val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_small)
|
val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_small)
|
||||||
|
|
||||||
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
||||||
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
|
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
|
||||||
appWidgetView.setImageViewBitmap(
|
appWidgetView.setImageViewBitmap(R.id.button_next, createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_next_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
|
||||||
R.id.button_next, createBitmap(
|
appWidgetView.setImageViewBitmap(R.id.button_prev, createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_previous_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
|
||||||
RetroUtil.getTintedVectorDrawable(
|
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_play_arrow_white_32dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
|
||||||
context,
|
|
||||||
R.drawable.ic_skip_next_white_24dp,
|
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
|
||||||
context, true
|
|
||||||
)
|
|
||||||
)!!, 1f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
appWidgetView.setImageViewBitmap(
|
|
||||||
R.id.button_prev, createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.ic_skip_previous_white_24dp,
|
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
|
||||||
context, true
|
|
||||||
)
|
|
||||||
)!!, 1f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
appWidgetView.setImageViewBitmap(
|
|
||||||
R.id.button_toggle_play_pause, createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.ic_play_arrow_white_32dp,
|
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
|
||||||
context, true
|
|
||||||
)
|
|
||||||
)!!, 1f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
linkButtons(context, appWidgetView)
|
linkButtons(context, appWidgetView)
|
||||||
pushUpdate(context, appWidgetIds, appWidgetView)
|
pushUpdate(context, appWidgetIds, appWidgetView)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update all active widget instances by pushing changes
|
* Update all active widget instances by pushing changes
|
||||||
*/
|
*/
|
||||||
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
|
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
|
||||||
val appWidgetView = RemoteViews(
|
val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_small)
|
||||||
service.packageName, R.layout.app_widget_small
|
|
||||||
)
|
|
||||||
|
|
||||||
val isPlaying = service.isPlaying
|
val isPlaying = service.isPlaying
|
||||||
val song = service.currentSong
|
val song = service.currentSong
|
||||||
|
|
||||||
// Set the titles and artwork
|
// Set the titles and artwork
|
||||||
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
|
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
|
||||||
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
||||||
} else {
|
} else {
|
||||||
if (TextUtils.isEmpty(song.title) || TextUtils.isEmpty(song.artistName)) {
|
if (TextUtils.isEmpty(song.title) || TextUtils.isEmpty(song.artistName)) {
|
||||||
appWidgetView.setTextViewText(R.id.text_separator, "")
|
appWidgetView.setTextViewText(R.id.text_separator, "")
|
||||||
} else {
|
} else {
|
||||||
appWidgetView.setTextViewText(R.id.text_separator, "•")
|
appWidgetView.setTextViewText(R.id.text_separator, "•")
|
||||||
}
|
}
|
||||||
|
|
||||||
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
|
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
|
||||||
appWidgetView.setTextViewText(R.id.title, song.title)
|
appWidgetView.setTextViewText(R.id.title, song.title)
|
||||||
appWidgetView.setTextViewText(R.id.text, song.artistName)
|
appWidgetView.setTextViewText(R.id.text, song.artistName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link actions buttons to intents
|
// Link actions buttons to intents
|
||||||
linkButtons(service, appWidgetView)
|
linkButtons(service, appWidgetView)
|
||||||
|
|
||||||
if (imageSize == 0) {
|
if (imageSize == 0) {
|
||||||
imageSize = service.resources.getDimensionPixelSize(R.dimen.app_widget_small_image_size)
|
imageSize = service.resources.getDimensionPixelSize(R.dimen.app_widget_small_image_size)
|
||||||
}
|
}
|
||||||
if (cardRadius == 0f) {
|
if (cardRadius == 0f) {
|
||||||
cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius)
|
cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the album cover async and push the update on completion
|
// Load the album cover async and push the update on completion
|
||||||
val appContext = service.applicationContext
|
val appContext = service.applicationContext
|
||||||
service.runOnUiThread {
|
service.runOnUiThread {
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
Glide.clear(target)
|
Glide.clear(target)
|
||||||
}
|
}
|
||||||
target = SongGlideRequest.Builder.from(Glide.with(service), song)
|
target = SongGlideRequest.Builder.from(Glide.with(service), song)
|
||||||
.checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop()
|
.checkIgnoreMediaStore(service).generatePalette(service).build().centerCrop()
|
||||||
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
|
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
|
||||||
override fun onResourceReady(
|
override fun onResourceReady(
|
||||||
resource: BitmapPaletteWrapper,
|
resource: BitmapPaletteWrapper,
|
||||||
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>
|
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>
|
||||||
) {
|
) {
|
||||||
val palette = resource.palette
|
val palette = resource.palette
|
||||||
update(
|
update(
|
||||||
resource.bitmap, palette.getVibrantColor(
|
resource.bitmap, palette.getVibrantColor(
|
||||||
palette.getMutedColor(
|
palette.getMutedColor(
|
||||||
MaterialValueHelper.getSecondaryTextColor(
|
MaterialValueHelper.getSecondaryTextColor(
|
||||||
service, true
|
service, true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
||||||
super.onLoadFailed(e, errorDrawable)
|
super.onLoadFailed(e, errorDrawable)
|
||||||
update(null, MaterialValueHelper.getSecondaryTextColor(service, true))
|
update(null, MaterialValueHelper.getSecondaryTextColor(service, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun update(bitmap: Bitmap?, color: Int) {
|
private fun update(bitmap: Bitmap?, color: Int) {
|
||||||
// Set correct drawable for pause state
|
// Set correct drawable for pause state
|
||||||
val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp
|
val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp
|
||||||
else R.drawable.ic_play_arrow_white_32dp
|
else R.drawable.ic_play_arrow_white_32dp
|
||||||
appWidgetView.setImageViewBitmap(
|
appWidgetView.setImageViewBitmap(
|
||||||
R.id.button_toggle_play_pause, createBitmap(
|
R.id.button_toggle_play_pause, createBitmap(
|
||||||
RetroUtil.getTintedVectorDrawable(
|
RetroUtil.getTintedVectorDrawable(
|
||||||
service, playPauseRes, color
|
service, playPauseRes, color
|
||||||
)!!, 1f
|
)!!, 1f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set prev/next button drawables
|
// Set prev/next button drawables
|
||||||
appWidgetView.setImageViewBitmap(
|
appWidgetView.setImageViewBitmap(
|
||||||
R.id.button_next, createBitmap(
|
R.id.button_next, createBitmap(
|
||||||
RetroUtil.getTintedVectorDrawable(
|
RetroUtil.getTintedVectorDrawable(
|
||||||
service, R.drawable.ic_skip_next_white_24dp, color
|
service, R.drawable.ic_skip_next_white_24dp, color
|
||||||
)!!, 1f
|
)!!, 1f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
appWidgetView.setImageViewBitmap(
|
appWidgetView.setImageViewBitmap(
|
||||||
R.id.button_prev, createBitmap(
|
R.id.button_prev, createBitmap(
|
||||||
RetroUtil.getTintedVectorDrawable(
|
RetroUtil.getTintedVectorDrawable(
|
||||||
service, R.drawable.ic_skip_previous_white_24dp, color
|
service, R.drawable.ic_skip_previous_white_24dp, color
|
||||||
)!!, 1f
|
)!!, 1f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val image = getAlbumArtDrawable(service.resources, bitmap)
|
val image = getAlbumArtDrawable(service.resources, bitmap)
|
||||||
val roundedBitmap = createRoundedBitmap(
|
val roundedBitmap = createRoundedBitmap(
|
||||||
image, imageSize, imageSize, cardRadius, 0f, 0f, 0f
|
image, imageSize, imageSize, cardRadius, 0f, 0f, 0f
|
||||||
)
|
)
|
||||||
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
||||||
|
|
||||||
pushUpdate(appContext, appWidgetIds, appWidgetView)
|
pushUpdate(appContext, appWidgetIds, appWidgetView)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link up various button actions using [PendingIntent].
|
* Link up various button actions using [PendingIntent].
|
||||||
*/
|
*/
|
||||||
private fun linkButtons(context: Context, views: RemoteViews) {
|
private fun linkButtons(context: Context, views: RemoteViews) {
|
||||||
val action = Intent(context, MainActivity::class.java).putExtra("expand", true)
|
val action = Intent(context, MainActivity::class.java).putExtra("expand", true)
|
||||||
var pendingIntent: PendingIntent
|
var pendingIntent: PendingIntent
|
||||||
|
|
||||||
val serviceName = ComponentName(context, MusicService::class.java)
|
val serviceName = ComponentName(context, MusicService::class.java)
|
||||||
|
|
||||||
// Home
|
// Home
|
||||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
|
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
|
||||||
views.setOnClickPendingIntent(R.id.image, pendingIntent)
|
views.setOnClickPendingIntent(R.id.image, pendingIntent)
|
||||||
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
|
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
|
||||||
|
|
||||||
// Previous track
|
// Previous track
|
||||||
pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName)
|
||||||
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
|
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
|
||||||
|
|
||||||
// Play and pause
|
// Play and pause
|
||||||
pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName)
|
||||||
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
|
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
|
||||||
|
|
||||||
// Next track
|
// Next track
|
||||||
pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName)
|
||||||
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
|
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val NAME: String = "app_widget_small"
|
const val NAME: String = "app_widget_small"
|
||||||
|
|
||||||
private var mInstance: AppWidgetSmall? = null
|
private var mInstance: AppWidgetSmall? = null
|
||||||
private var imageSize = 0
|
private var imageSize = 0
|
||||||
private var cardRadius = 0f
|
private var cardRadius = 0f
|
||||||
|
|
||||||
val instance: AppWidgetSmall
|
val instance: AppWidgetSmall
|
||||||
@Synchronized get() {
|
@Synchronized get() {
|
||||||
if (mInstance == null) {
|
if (mInstance == null) {
|
||||||
mInstance = AppWidgetSmall()
|
mInstance = AppWidgetSmall()
|
||||||
}
|
}
|
||||||
return mInstance!!
|
return mInstance!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,18 @@
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger
|
package code.name.monkey.retromusic.dagger
|
||||||
|
|
||||||
import code.name.monkey.retromusic.activities.*
|
import code.name.monkey.retromusic.activities.AlbumDetailsActivity
|
||||||
import code.name.monkey.retromusic.dagger.module.*
|
import code.name.monkey.retromusic.activities.ArtistDetailActivity
|
||||||
import code.name.monkey.retromusic.fragments.mainactivity.*
|
import code.name.monkey.retromusic.activities.GenreDetailsActivity
|
||||||
|
import code.name.monkey.retromusic.activities.PlaylistDetailActivity
|
||||||
|
import code.name.monkey.retromusic.activities.SearchActivity
|
||||||
|
import code.name.monkey.retromusic.dagger.module.AppModule
|
||||||
|
import code.name.monkey.retromusic.dagger.module.PresenterModule
|
||||||
|
import code.name.monkey.retromusic.fragments.mainactivity.AlbumsFragment
|
||||||
|
import code.name.monkey.retromusic.fragments.mainactivity.ArtistsFragment
|
||||||
|
import code.name.monkey.retromusic.fragments.mainactivity.GenresFragment
|
||||||
|
import code.name.monkey.retromusic.fragments.mainactivity.PlaylistsFragment
|
||||||
|
import code.name.monkey.retromusic.fragments.mainactivity.SongsFragment
|
||||||
import code.name.monkey.retromusic.fragments.mainactivity.home.BannerHomeFragment
|
import code.name.monkey.retromusic.fragments.mainactivity.home.BannerHomeFragment
|
||||||
import dagger.Component
|
import dagger.Component
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -25,17 +34,12 @@ import javax.inject.Singleton
|
||||||
* Created by hemanths on 2019-09-04.
|
* Created by hemanths on 2019-09-04.
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
@Component(modules = [
|
@Component(
|
||||||
RepositoryModule::class,
|
modules = [
|
||||||
AlbumModule::class,
|
AppModule::class,
|
||||||
ArtistModule::class,
|
PresenterModule::class
|
||||||
GenreModule::class,
|
]
|
||||||
HomeModule::class,
|
)
|
||||||
PlaylistModule::class,
|
|
||||||
SearchModule::class,
|
|
||||||
SongModule::class,
|
|
||||||
ActivityModule::class
|
|
||||||
])
|
|
||||||
interface MusicComponent {
|
interface MusicComponent {
|
||||||
|
|
||||||
fun inject(songsFragment: SongsFragment)
|
fun inject(songsFragment: SongsFragment)
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class ActivityModule(private val activity: Activity) {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
fun provideActivity(): Activity {
|
|
||||||
return activity
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter.AlbumDetailsPresenterImpl
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter.AlbumsPresenterImpl
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class AlbumModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesAlbumsPresenter(presenter: AlbumsPresenterImpl): AlbumsPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesAlbumDetailsPresenter(presenter: AlbumDetailsPresenterImpl): AlbumDetailsPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
package code.name.monkey.retromusic.dagger.module
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
@ -24,11 +25,9 @@ import javax.inject.Singleton
|
||||||
* Created by hemanths on 2019-09-04.
|
* Created by hemanths on 2019-09-04.
|
||||||
*/
|
*/
|
||||||
@Module
|
@Module
|
||||||
class AppModule(private val context: Context) {
|
class AppModule(private val application: Application) {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideContext(): Context {
|
fun provideContext(): Context = application
|
||||||
return context
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter.ArtistDetailsPresenterImpl
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter.ArtistsPresenterImpl
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class ArtistModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesArtistDetailsPresenter(presenter: ArtistDetailsPresenterImpl): ArtistDetailsPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesArtistsPresenter(presenter: ArtistsPresenterImpl): ArtistsPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter.GenreDetailsPresenterImpl
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.GenresPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.GenresPresenter.GenresPresenterImpl
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class GenreModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesGenresPresenter(presenter: GenresPresenterImpl): GenresPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesGenreDetailsPresenter(presenter: GenreDetailsPresenterImpl): GenreDetailsPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.HomePresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.HomePresenter.HomePresenterImpl
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class HomeModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesHomePresenter(presenter: HomePresenterImpl): HomePresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter.PlaylistSongsPresenterImpl
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter.PlaylistsPresenterImpl
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class PlaylistModule {
|
|
||||||
@Provides
|
|
||||||
fun providesPlaylistSongPresenter(presenter: PlaylistSongsPresenterImpl): PlaylistSongsPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesPlaylistsPresenter(presenter: PlaylistsPresenterImpl): PlaylistsPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Hemanth Savarala.
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License v3
|
||||||
|
*
|
||||||
|
* This is free software: you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package code.name.monkey.retromusic.dagger.module
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter.AlbumDetailsPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter.AlbumsPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter.ArtistDetailsPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter.ArtistsPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter.GenreDetailsPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.GenresPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.GenresPresenter.GenresPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.HomePresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.HomePresenter.HomePresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter.PlaylistSongsPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter.PlaylistsPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter.SearchPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.SongPresenter
|
||||||
|
import code.name.monkey.retromusic.mvp.presenter.SongPresenter.SongPresenterImpl
|
||||||
|
import code.name.monkey.retromusic.providers.RepositoryImpl
|
||||||
|
import code.name.monkey.retromusic.providers.interfaces.Repository
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hemanths on 2019-12-30.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Module
|
||||||
|
class PresenterModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesRepository(context: Context): Repository {
|
||||||
|
return RepositoryImpl(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesAlbumsPresenter(presenter: AlbumsPresenterImpl): AlbumsPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesAlbumDetailsPresenter(presenter: AlbumDetailsPresenterImpl): AlbumDetailsPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesArtistDetailsPresenter(presenter: ArtistDetailsPresenterImpl): ArtistDetailsPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesArtistsPresenter(presenter: ArtistsPresenterImpl): ArtistsPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesGenresPresenter(presenter: GenresPresenterImpl): GenresPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesGenreDetailsPresenter(presenter: GenreDetailsPresenterImpl): GenreDetailsPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesHomePresenter(presenter: HomePresenterImpl): HomePresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesPlaylistSongPresenter(presenter: PlaylistSongsPresenterImpl): PlaylistSongsPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesPlaylistsPresenter(presenter: PlaylistsPresenterImpl): PlaylistsPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesSearchPresenter(presenter: SearchPresenterImpl): SearchPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun providesSongPresenter(presenter: SongPresenterImpl): SongPresenter {
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import code.name.monkey.retromusic.providers.RepositoryImpl
|
|
||||||
import code.name.monkey.retromusic.providers.interfaces.Repository
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module(includes = [AppModule::class])
|
|
||||||
class RepositoryModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesRepository(context: Context): Repository {
|
|
||||||
return RepositoryImpl(context)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter.SearchPresenterImpl
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class SearchModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesSearchPresenter(presenter: SearchPresenterImpl): SearchPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.dagger.module
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SongPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SongPresenter.SongPresenterImpl
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
class SongModule {
|
|
||||||
@Provides
|
|
||||||
fun providesSongPresenter(presenter: SongPresenterImpl): SongPresenter {
|
|
||||||
return presenter
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,7 +13,9 @@ import code.name.monkey.retromusic.mvp.presenter.AlbumsView
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager>(), AlbumsView {
|
open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager>(),
|
||||||
|
AlbumsView {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var albumsPresenter: AlbumsPresenter
|
lateinit var albumsPresenter: AlbumsPresenter
|
||||||
|
|
||||||
|
@ -73,7 +75,6 @@ open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<Al
|
||||||
adapter?.notifyDataSetChanged()
|
adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun loadSortOrder(): String {
|
override fun loadSortOrder(): String {
|
||||||
|
|
||||||
return PreferenceUtil.getInstance(requireContext()).albumSortOrder
|
return PreferenceUtil.getInstance(requireContext()).albumSortOrder
|
||||||
|
@ -117,7 +118,6 @@ open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<Al
|
||||||
albumsPresenter.loadAlbums()
|
albumsPresenter.loadAlbums()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun showEmptyView() {
|
override fun showEmptyView() {
|
||||||
adapter?.swapDataSet(ArrayList())
|
adapter?.swapDataSet(ArrayList())
|
||||||
}
|
}
|
||||||
|
@ -133,5 +133,4 @@ open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<Al
|
||||||
return fragment
|
return fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,16 @@ package code.name.monkey.retromusic.mvp.presenter
|
||||||
|
|
||||||
import code.name.monkey.retromusic.Result
|
import code.name.monkey.retromusic.Result
|
||||||
import code.name.monkey.retromusic.model.Album
|
import code.name.monkey.retromusic.model.Album
|
||||||
import code.name.monkey.retromusic.mvp.*
|
import code.name.monkey.retromusic.mvp.BaseView
|
||||||
|
import code.name.monkey.retromusic.mvp.Presenter
|
||||||
|
import code.name.monkey.retromusic.mvp.PresenterImpl
|
||||||
import code.name.monkey.retromusic.providers.interfaces.Repository
|
import code.name.monkey.retromusic.providers.interfaces.Repository
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import java.util.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.ArrayList
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
@ -35,7 +41,7 @@ interface AlbumsPresenter : Presenter<AlbumsView> {
|
||||||
fun loadAlbums()
|
fun loadAlbums()
|
||||||
|
|
||||||
class AlbumsPresenterImpl @Inject constructor(
|
class AlbumsPresenterImpl @Inject constructor(
|
||||||
private val repository: Repository
|
private val repository: Repository
|
||||||
) : PresenterImpl<AlbumsView>(), AlbumsPresenter, CoroutineScope {
|
) : PresenterImpl<AlbumsView>(), AlbumsPresenter, CoroutineScope {
|
||||||
private val job = Job()
|
private val job = Job()
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,29 @@ import code.name.monkey.retromusic.Result
|
||||||
import code.name.monkey.retromusic.Result.Error
|
import code.name.monkey.retromusic.Result.Error
|
||||||
import code.name.monkey.retromusic.Result.Success
|
import code.name.monkey.retromusic.Result.Success
|
||||||
import code.name.monkey.retromusic.adapter.HomeAdapter
|
import code.name.monkey.retromusic.adapter.HomeAdapter
|
||||||
import code.name.monkey.retromusic.loaders.*
|
import code.name.monkey.retromusic.loaders.AlbumLoader
|
||||||
import code.name.monkey.retromusic.model.*
|
import code.name.monkey.retromusic.loaders.ArtistLoader
|
||||||
|
import code.name.monkey.retromusic.loaders.GenreLoader
|
||||||
|
import code.name.monkey.retromusic.loaders.LastAddedSongsLoader
|
||||||
|
import code.name.monkey.retromusic.loaders.PlaylistLoader
|
||||||
|
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
|
||||||
|
import code.name.monkey.retromusic.loaders.SearchLoader
|
||||||
|
import code.name.monkey.retromusic.loaders.SongLoader
|
||||||
|
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader
|
||||||
|
import code.name.monkey.retromusic.model.AbsCustomPlaylist
|
||||||
|
import code.name.monkey.retromusic.model.Album
|
||||||
|
import code.name.monkey.retromusic.model.Artist
|
||||||
|
import code.name.monkey.retromusic.model.Genre
|
||||||
|
import code.name.monkey.retromusic.model.Home
|
||||||
|
import code.name.monkey.retromusic.model.Playlist
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.providers.interfaces.Repository
|
import code.name.monkey.retromusic.providers.interfaces.Repository
|
||||||
import code.name.monkey.retromusic.rest.LastFMRestClient
|
import code.name.monkey.retromusic.rest.LastFMRestClient
|
||||||
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RepositoryImpl(private val context: Context) : Repository {
|
class RepositoryImpl @Inject constructor(private val context: Context) : Repository {
|
||||||
|
|
||||||
override suspend fun allAlbums(): Result<ArrayList<Album>> {
|
override suspend fun allAlbums(): Result<ArrayList<Album>> {
|
||||||
return try {
|
return try {
|
||||||
|
@ -152,11 +167,15 @@ class RepositoryImpl(private val context: Context) : Repository {
|
||||||
if (artists.isEmpty()) {
|
if (artists.isEmpty()) {
|
||||||
Error(Throwable("No items found"))
|
Error(Throwable("No items found"))
|
||||||
} else {
|
} else {
|
||||||
Success(Home(0,
|
Success(
|
||||||
|
Home(
|
||||||
|
0,
|
||||||
R.string.recent_artists,
|
R.string.recent_artists,
|
||||||
artists,
|
artists,
|
||||||
HomeAdapter.RECENT_ARTISTS,
|
HomeAdapter.RECENT_ARTISTS,
|
||||||
R.drawable.ic_artist_white_24dp))
|
R.drawable.ic_artist_white_24dp
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Error(e)
|
Error(e)
|
||||||
|
@ -169,12 +188,15 @@ class RepositoryImpl(private val context: Context) : Repository {
|
||||||
if (albums.isEmpty()) {
|
if (albums.isEmpty()) {
|
||||||
Error(Throwable("No items found"))
|
Error(Throwable("No items found"))
|
||||||
} else {
|
} else {
|
||||||
Success(Home(1,
|
Success(
|
||||||
|
Home(
|
||||||
|
1,
|
||||||
R.string.recent_albums,
|
R.string.recent_albums,
|
||||||
albums,
|
albums,
|
||||||
HomeAdapter.RECENT_ALBUMS,
|
HomeAdapter.RECENT_ALBUMS,
|
||||||
R.drawable.ic_album_white_24dp
|
R.drawable.ic_album_white_24dp
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Error(e)
|
Error(e)
|
||||||
|
@ -187,31 +209,36 @@ class RepositoryImpl(private val context: Context) : Repository {
|
||||||
if (albums.isEmpty()) {
|
if (albums.isEmpty()) {
|
||||||
Error(Throwable("No items found"))
|
Error(Throwable("No items found"))
|
||||||
} else {
|
} else {
|
||||||
Success(Home(3,
|
Success(
|
||||||
|
Home(
|
||||||
|
3,
|
||||||
R.string.top_albums,
|
R.string.top_albums,
|
||||||
albums,
|
albums,
|
||||||
HomeAdapter.TOP_ALBUMS,
|
HomeAdapter.TOP_ALBUMS,
|
||||||
R.drawable.ic_album_white_24dp
|
R.drawable.ic_album_white_24dp
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Error(e)
|
Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override suspend fun topArtists(): Result<Home> {
|
override suspend fun topArtists(): Result<Home> {
|
||||||
return try {
|
return try {
|
||||||
val artists = TopAndRecentlyPlayedTracksLoader.getTopArtists(context)
|
val artists = TopAndRecentlyPlayedTracksLoader.getTopArtists(context)
|
||||||
if (artists.isEmpty()) {
|
if (artists.isEmpty()) {
|
||||||
Error(Throwable("No items found"))
|
Error(Throwable("No items found"))
|
||||||
} else {
|
} else {
|
||||||
Success(Home(2,
|
Success(
|
||||||
|
Home(
|
||||||
|
2,
|
||||||
R.string.top_artists,
|
R.string.top_artists,
|
||||||
artists,
|
artists,
|
||||||
HomeAdapter.TOP_ARTISTS,
|
HomeAdapter.TOP_ARTISTS,
|
||||||
R.drawable.ic_artist_white_24dp
|
R.drawable.ic_artist_white_24dp
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Error(e)
|
Error(e)
|
||||||
|
@ -224,12 +251,15 @@ class RepositoryImpl(private val context: Context) : Repository {
|
||||||
if (playlists.isEmpty()) {
|
if (playlists.isEmpty()) {
|
||||||
Error(Throwable("No items found"))
|
Error(Throwable("No items found"))
|
||||||
} else {
|
} else {
|
||||||
Success(Home(4,
|
Success(
|
||||||
|
Home(
|
||||||
|
4,
|
||||||
R.string.favorites,
|
R.string.favorites,
|
||||||
playlists,
|
playlists,
|
||||||
HomeAdapter.PLAYLISTS,
|
HomeAdapter.PLAYLISTS,
|
||||||
R.drawable.ic_favorite_white_24dp
|
R.drawable.ic_favorite_white_24dp
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Error(e)
|
Error(e)
|
||||||
|
@ -237,14 +267,14 @@ class RepositoryImpl(private val context: Context) : Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun artistInfo(
|
override suspend fun artistInfo(
|
||||||
name: String,
|
name: String,
|
||||||
lang: String?,
|
lang: String?,
|
||||||
cache: String?
|
cache: String?
|
||||||
): Result<LastFmArtist> = safeApiCall(
|
): Result<LastFmArtist> = safeApiCall(
|
||||||
call = {
|
call = {
|
||||||
Success(LastFMRestClient(context).apiService.artistInfo(name, lang, cache))
|
Success(LastFMRestClient(context).apiService.artistInfo(name, lang, cache))
|
||||||
},
|
},
|
||||||
errorMessage = "Error"
|
errorMessage = "Error"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -12,24 +12,24 @@
|
||||||
~ See the GNU General Public License for more details.
|
~ See the GNU General Public License for more details.
|
||||||
-->
|
-->
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:id="@android:id/background">
|
<item android:id="@android:id/background">
|
||||||
<shape
|
<shape
|
||||||
android:dither="true"
|
android:dither="true"
|
||||||
android:shape="ring"
|
android:shape="ring"
|
||||||
android:thickness="3dp"
|
android:thickness="3dp"
|
||||||
android:type="sweep"
|
android:type="sweep"
|
||||||
android:useLevel="false">
|
android:useLevel="false">
|
||||||
<solid android:color="?android:attr/textColorSecondary" />
|
<solid android:color="?android:attr/textColorSecondary" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item android:id="@android:id/progress">
|
<item android:id="@android:id/progress">
|
||||||
<shape
|
<shape
|
||||||
android:shape="ring"
|
android:shape="ring"
|
||||||
android:thickness="3dp"
|
android:thickness="3dp"
|
||||||
android:type="sweep"
|
android:type="sweep"
|
||||||
android:useLevel="true">
|
android:useLevel="true">
|
||||||
<solid android:color="?attr/colorAccent" />
|
<solid android:color="?attr/colorAccent" />
|
||||||
<corners android:radius="4dp" />
|
<corners android:radius="4dp" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
|
@ -18,7 +18,6 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/appBarLayout"
|
android:id="@+id/appBarLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -1,96 +1,96 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/content"
|
android:id="@+id/content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/app_widget_classic_height"
|
||||||
|
android:background="@color/md_black_1000"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="ContentDescription">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="@dimen/app_widget_classic_image_size"
|
||||||
|
android:layout_height="@dimen/app_widget_classic_image_size"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/app_widget_classic_height"
|
android:layout_height="match_parent">
|
||||||
android:background="@color/md_black_1000"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
tools:ignore="ContentDescription">
|
|
||||||
|
|
||||||
<ImageView
|
<LinearLayout
|
||||||
android:id="@+id/image"
|
android:id="@+id/media_actions"
|
||||||
android:layout_width="@dimen/app_widget_classic_image_size"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/app_widget_classic_image_size"
|
android:layout_height="wrap_content"
|
||||||
android:scaleType="centerCrop" />
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layoutDirection="ltr"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
<RelativeLayout
|
<ImageButton
|
||||||
|
android:id="@+id/button_prev"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/widget_selector"
|
||||||
|
tools:src="@drawable/ic_skip_previous_white_24dp"
|
||||||
|
tools:tint="@color/ate_secondary_text_dark" />
|
||||||
|
|
||||||
<LinearLayout
|
<ImageButton
|
||||||
android:id="@+id/media_actions"
|
android:id="@+id/button_toggle_play_pause"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_weight="1"
|
||||||
android:layout_gravity="bottom"
|
android:background="@drawable/widget_selector"
|
||||||
android:layoutDirection="ltr"
|
tools:src="@drawable/ic_play_arrow_white_32dp"
|
||||||
android:orientation="horizontal"
|
tools:tint="@color/ate_secondary_text_dark" />
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/button_prev"
|
android:id="@+id/button_next"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/widget_selector"
|
android:background="@drawable/widget_selector"
|
||||||
tools:src="@drawable/ic_skip_previous_white_24dp"
|
tools:src="@drawable/ic_skip_next_white_24dp"
|
||||||
tools:tint="@color/ate_secondary_text_dark" />
|
tools:tint="@color/ate_secondary_text_dark" />
|
||||||
|
|
||||||
<ImageButton
|
</LinearLayout>
|
||||||
android:id="@+id/button_toggle_play_pause"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/widget_selector"
|
|
||||||
tools:src="@drawable/ic_play_arrow_white_32dp"
|
|
||||||
tools:tint="@color/ate_secondary_text_dark" />
|
|
||||||
|
|
||||||
<ImageButton
|
<LinearLayout
|
||||||
android:id="@+id/button_next"
|
android:id="@+id/media_titles"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_above="@+id/media_actions"
|
||||||
android:background="@drawable/widget_selector"
|
android:layout_alignParentTop="true"
|
||||||
tools:src="@drawable/ic_skip_next_white_24dp"
|
android:orientation="vertical"
|
||||||
tools:tint="@color/ate_secondary_text_dark" />
|
android:paddingStart="8dp"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:paddingEnd="8dp">
|
||||||
|
|
||||||
</LinearLayout>
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextViewSubtitle1"
|
||||||
|
android:textColor="@color/ate_primary_text_dark"
|
||||||
|
tools:text="Title" />
|
||||||
|
|
||||||
<LinearLayout
|
<TextView
|
||||||
android:id="@+id/media_titles"
|
android:id="@+id/text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_above="@+id/media_actions"
|
android:gravity="center_vertical"
|
||||||
android:layout_alignParentTop="true"
|
android:paddingTop="4dp"
|
||||||
android:orientation="vertical"
|
android:singleLine="true"
|
||||||
android:paddingStart="8dp"
|
android:textAppearance="@style/TextViewNormal"
|
||||||
android:paddingTop="4dp"
|
android:textColor="@color/ate_secondary_text_dark"
|
||||||
android:paddingEnd="8dp">
|
tools:text="Text" />
|
||||||
|
|
||||||
<TextView
|
</LinearLayout>
|
||||||
android:id="@+id/title"
|
</RelativeLayout>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/TextViewSubtitle1"
|
|
||||||
android:textColor="@color/ate_primary_text_dark"
|
|
||||||
tools:text="Title" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/TextViewNormal"
|
|
||||||
android:textColor="@color/ate_secondary_text_dark"
|
|
||||||
tools:text="Text" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -9,3 +9,4 @@ android.enableJetifier=true
|
||||||
android.debug.obsoleteApi=true
|
android.debug.obsoleteApi=true
|
||||||
android.enableBuildCache=true
|
android.enableBuildCache=true
|
||||||
android.jetifier.blacklist = butterknife.*\\.jar
|
android.jetifier.blacklist = butterknife.*\\.jar
|
||||||
|
kotlin.code.style=official
|
Loading…
Reference in a new issue