Merge branch 'Better_Player' into dev

# Conflicts:
#	app/build.gradle
This commit is contained in:
Prathamesh More 2022-05-26 20:16:44 +05:30
commit 5d0b5b91b0
175 changed files with 2308 additions and 2845 deletions

View file

@ -15,7 +15,7 @@ android {
applicationId "code.name.monkey.retromusic" applicationId "code.name.monkey.retromusic"
versionCode 10584 versionCode 10584
versionName '5.8.4' versionName '5.9.0'
buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"") buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"")
} }
@ -51,8 +51,7 @@ android {
} }
} }
lint { lint {
abortOnError false disable 'MissingTranslation', 'ImpliedQuantity'
disable 'MissingTranslation', 'InvalidPackage'
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
@ -90,7 +89,7 @@ dependencies {
implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.appcompat:appcompat:$appcompat_version" implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation 'androidx.annotation:annotation:1.3.0' implementation 'androidx.annotation:annotation:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation "androidx.preference:preference-ktx:$preference_version" implementation "androidx.preference:preference-ktx:$preference_version"
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.7.0'
@ -116,9 +115,11 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
implementation "androidx.core:core-splashscreen:1.0.0-beta02" implementation "androidx.core:core-splashscreen:1.0.0-rc01"
implementation 'com.google.android.play:feature-delivery:2.0.0'
implementation 'com.google.android.play:review:2.0.0'
implementation 'com.google.android.play:core-ktx:1.8.1'
implementation "com.google.android.material:material:$mdc_version" implementation "com.google.android.material:material:$mdc_version"
def retrofit_version = '2.9.0' def retrofit_version = '2.9.0'
@ -165,6 +166,6 @@ dependencies {
implementation 'com.github.dhaval2404:imagepicker:2.1' implementation 'com.github.dhaval2404:imagepicker:2.1'
implementation 'me.zhanghai.android.fastscroll:library:1.1.8' implementation 'me.zhanghai.android.fastscroll:library:1.1.8'
implementation 'cat.ereza:customactivityoncrash:2.3.0' implementation 'cat.ereza:customactivityoncrash:2.3.0'
implementation 'me.tankery.lib:circularSeekBar:1.3.2' implementation 'me.tankery.lib:circularSeekBar:1.4.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
} }

View file

@ -23,7 +23,10 @@
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission
android:name="android.permission.BLUETOOTH_CONNECT"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s" />
<application <application
android:name=".App" android:name=".App"
@ -113,7 +116,6 @@
<data android:mimeType="vnd.android.cursor.dir/audio" /> <data android:mimeType="vnd.android.cursor.dir/audio" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".activities.SettingsActivity" />
<activity android:name=".activities.tageditor.AlbumTagEditorActivity" /> <activity android:name=".activities.tageditor.AlbumTagEditorActivity" />
<activity android:name=".activities.tageditor.SongTagEditorActivity" /> <activity android:name=".activities.tageditor.SongTagEditorActivity" />
<activity android:name=".activities.SupportDevelopmentActivity" /> <activity android:name=".activities.SupportDevelopmentActivity" />
@ -123,7 +125,10 @@
<activity android:name=".activities.ShareInstagramStory" /> <activity android:name=".activities.ShareInstagramStory" />
<activity android:name=".activities.DriveModeActivity" /> <activity android:name=".activities.DriveModeActivity" />
<activity android:name=".activities.PermissionActivity" /> <activity android:name=".activities.PermissionActivity" />
<activity android:name=".activities.LockScreenActivity" /> <activity
android:name=".activities.LockScreenActivity"
android:launchMode="singleTop"
android:showOnLockScreen="true" />
<activity <activity
android:name=".fragments.backup.RestoreActivity" android:name=".fragments.backup.RestoreActivity"
android:excludeFromRecents="false" android:excludeFromRecents="false"
@ -170,20 +175,6 @@
android:name=".activities.saf.SAFGuideActivity" android:name=".activities.saf.SAFGuideActivity"
android:theme="@style/Theme.Intro" /> android:theme="@style/Theme.Intro" />
<activity
android:name=".cast.ExpandedControlsActivity"
android:exported="true"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity <activity
android:name=".activities.ErrorActivity" android:name=".activities.ErrorActivity"
android:exported="true"> android:exported="true">
@ -192,16 +183,6 @@
</intent-filter> </intent-filter>
</activity> </activity>
<provider
android:name=".misc.GenericFileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}" android:authorities="${applicationId}"

View file

@ -62,6 +62,19 @@
</head> </head>
<body> <body>
<div>
<h5>May 14, 2022</h5>
<h2>v5.9.0</h2>
<h3>What's New</h3>
<ul>
<li>Better Cast</li>
<li>Mini player in settings screen</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fixed Top/Recent Artists/Albums not updating (Wrong sort order)</li>
</ul>
</div>
<div> <div>
<h5>May 13, 2022</h5> <h5>May 13, 2022</h5>
<h2>v5.8.4</h2> <h2>v5.8.4</h2>

View file

@ -20,6 +20,7 @@ import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
import code.name.monkey.retromusic.activities.ErrorActivity import code.name.monkey.retromusic.activities.ErrorActivity
import code.name.monkey.retromusic.activities.MainActivity
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.helper.WallpaperAccentManager import code.name.monkey.retromusic.helper.WallpaperAccentManager
@ -69,7 +70,7 @@ class App : Application() {
}) })
// setting Error activity // setting Error activity
CaocConfig.Builder.create().errorActivity(ErrorActivity::class.java).apply() CaocConfig.Builder.create().errorActivity(ErrorActivity::class.java).restartActivity(MainActivity::class.java).apply()
} }
override fun onTerminate() { override fun onTerminate() {

View file

@ -88,12 +88,7 @@ const val CIRCULAR_ALBUM_ART = "circular_album_art"
const val USER_NAME = "user_name" const val USER_NAME = "user_name"
const val TOGGLE_FULL_SCREEN = "toggle_full_screen" const val TOGGLE_FULL_SCREEN = "toggle_full_screen"
const val TOGGLE_VOLUME = "toggle_volume" const val TOGGLE_VOLUME = "toggle_volume"
const val ROUND_CORNERS = "corner_window"
const val TOGGLE_GENRE = "toggle_genre"
const val PROFILE_IMAGE_PATH = "profile_image_path"
const val BANNER_IMAGE_PATH = "banner_image_path"
const val ADAPTIVE_COLOR_APP = "adaptive_color_app" const val ADAPTIVE_COLOR_APP = "adaptive_color_app"
const val TOGGLE_SEPARATE_LINE = "toggle_separate_line"
const val HOME_ARTIST_GRID_STYLE = "home_artist_grid_style" const val HOME_ARTIST_GRID_STYLE = "home_artist_grid_style"
const val HOME_ALBUM_GRID_STYLE = "home_album_grid_style" const val HOME_ALBUM_GRID_STYLE = "home_album_grid_style"
const val TOGGLE_ADD_CONTROLS = "toggle_add_controls" const val TOGGLE_ADD_CONTROLS = "toggle_add_controls"
@ -108,7 +103,6 @@ const val SAF_SDCARD_URI = "saf_sdcard_uri"
const val SONG_SORT_ORDER = "song_sort_order" const val SONG_SORT_ORDER = "song_sort_order"
const val SONG_GRID_SIZE = "song_grid_size" const val SONG_GRID_SIZE = "song_grid_size"
const val GENRE_SORT_ORDER = "genre_sort_order" const val GENRE_SORT_ORDER = "genre_sort_order"
const val LAST_PAGE = "last_start_page"
const val BLUETOOTH_PLAYBACK = "bluetooth_playback" const val BLUETOOTH_PLAYBACK = "bluetooth_playback"
const val INITIALIZED_BLACKLIST = "initialized_blacklist" const val INITIALIZED_BLACKLIST = "initialized_blacklist"
const val ARTIST_SORT_ORDER = "artist_sort_order" const val ARTIST_SORT_ORDER = "artist_sort_order"

View file

@ -3,17 +3,15 @@ package code.name.monkey.retromusic
import android.content.Context import android.content.Context
import android.content.ContextWrapper import android.content.ContextWrapper
import android.os.LocaleList import android.os.LocaleList
import code.name.monkey.appthemehelper.util.VersionUtils.hasNougatMR import code.name.monkey.appthemehelper.util.VersionUtils.hasNougat
import com.google.android.gms.common.annotation.KeepName
import java.util.* import java.util.*
class LanguageContextWrapper(base: Context?) : ContextWrapper(base) { class LanguageContextWrapper(base: Context?) : ContextWrapper(base) {
companion object { companion object {
@KeepName
fun wrap(context: Context?, newLocale: Locale?): LanguageContextWrapper { fun wrap(context: Context?, newLocale: Locale?): LanguageContextWrapper {
if (context == null) return LanguageContextWrapper(context) if (context == null) return LanguageContextWrapper(context)
val configuration = context.resources.configuration val configuration = context.resources.configuration
if (hasNougatMR()) { if (hasNougat()) {
configuration.setLocale(newLocale) configuration.setLocale(newLocale)
val localeList = LocaleList(newLocale) val localeList = LocaleList(newLocale)
LocaleList.setDefault(localeList) LocaleList.setDefault(localeList)

View file

@ -1,12 +1,9 @@
package code.name.monkey.retromusic package code.name.monkey.retromusic
import androidx.room.Room import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import code.name.monkey.retromusic.auto.AutoMusicProvider import code.name.monkey.retromusic.auto.AutoMusicProvider
import code.name.monkey.retromusic.cast.RetroWebServer import code.name.monkey.retromusic.cast.RetroWebServer
import code.name.monkey.retromusic.db.BlackListStoreDao import code.name.monkey.retromusic.db.MIGRATION_23_24
import code.name.monkey.retromusic.db.BlackListStoreEntity
import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.RetroDatabase import code.name.monkey.retromusic.db.RetroDatabase
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
@ -20,10 +17,6 @@ import code.name.monkey.retromusic.network.provideLastFmRest
import code.name.monkey.retromusic.network.provideLastFmRetrofit import code.name.monkey.retromusic.network.provideLastFmRetrofit
import code.name.monkey.retromusic.network.provideOkHttp import code.name.monkey.retromusic.network.provideOkHttp
import code.name.monkey.retromusic.repository.* import code.name.monkey.retromusic.repository.*
import code.name.monkey.retromusic.util.FilePathUtil
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.bind import org.koin.dsl.bind
@ -49,32 +42,14 @@ private val roomModule = module {
single { single {
Room.databaseBuilder(androidContext(), RetroDatabase::class.java, "playlist.db") Room.databaseBuilder(androidContext(), RetroDatabase::class.java, "playlist.db")
.allowMainThreadQueries() .addMigrations(MIGRATION_23_24)
.addCallback(object : RoomDatabase.Callback() {
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
GlobalScope.launch(IO) {
FilePathUtil.blacklistFilePaths().map {
get<BlackListStoreDao>().insertBlacklistPath(BlackListStoreEntity(it))
}
}
}
})
.fallbackToDestructiveMigration()
.build() .build()
} }
factory {
get<RetroDatabase>().lyricsDao()
}
factory { factory {
get<RetroDatabase>().playlistDao() get<RetroDatabase>().playlistDao()
} }
factory {
get<RetroDatabase>().blackListStore()
}
factory { factory {
get<RetroDatabase>().playCountDao() get<RetroDatabase>().playCountDao()
} }
@ -84,7 +59,7 @@ private val roomModule = module {
} }
single { single {
RealRoomRepository(get(), get(), get(), get(), get()) RealRoomRepository(get(), get(), get())
} bind RoomRepository::class } bind RoomRepository::class
} }
private val autoModule = module { private val autoModule = module {

View file

@ -20,7 +20,6 @@ import android.graphics.Color
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.view.animation.LinearInterpolator import android.view.animation.LinearInterpolator
import android.widget.SeekBar
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
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,11 +35,11 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import com.google.android.material.slider.Slider
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -113,17 +112,15 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
} }
private fun setUpProgressSlider() { private fun setUpProgressSlider() {
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() { binding.progressSlider.addOnChangeListener { _: Slider, progress: Float, fromUser: Boolean ->
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
MusicPlayerRemote.seekTo(progress) MusicPlayerRemote.seekTo(progress.toInt())
onUpdateProgressViews( onUpdateProgressViews(
MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songProgressMillis,
MusicPlayerRemote.songDurationMillis MusicPlayerRemote.songDurationMillis
) )
} }
} }
})
} }
override fun onPause() { override fun onPause() {
@ -249,9 +246,9 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
} }
override fun onUpdateProgressViews(progress: Int, total: Int) { override fun onUpdateProgressViews(progress: Int, total: Int) {
binding.progressSlider.max = total binding.progressSlider.valueTo = total.toFloat()
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress) val animator = ObjectAnimator.ofFloat(binding.progressSlider, "value", progress.toFloat())
animator.duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME animator.duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME
animator.interpolator = LinearInterpolator() animator.interpolator = LinearInterpolator()
animator.start() animator.start()

View file

@ -3,19 +3,19 @@ package code.name.monkey.retromusic.activities
import android.os.Bundle import android.os.Bundle
import android.widget.Button import android.widget.Button
import android.widget.ImageView import android.widget.ImageView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import cat.ereza.customactivityoncrash.CustomActivityOnCrash import cat.ereza.customactivityoncrash.CustomActivityOnCrash
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.util.FileUtils.createFile import code.name.monkey.retromusic.util.FileUtils.createFile
import code.name.monkey.retromusic.util.Share.shareFile import code.name.monkey.retromusic.util.Share.shareFile
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
class ErrorActivity : AppCompatActivity() { class ErrorActivity : AppCompatActivity() {
private val dayFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) private val dayFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
private val ReportPrefix = "bug_report-" private val reportPrefix = "bug_report-"
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.customactivityoncrash_default_error_activity) setContentView(R.layout.customactivityoncrash_default_error_activity)
@ -39,7 +39,7 @@ class ErrorActivity : AppCompatActivity() {
findViewById<Button>(R.id.customactivityoncrash_error_activity_more_info_button) findViewById<Button>(R.id.customactivityoncrash_error_activity_more_info_button)
moreInfoButton.setOnClickListener { //We retrieve all the error data and show it moreInfoButton.setOnClickListener { //We retrieve all the error data and show it
AlertDialog.Builder(this@ErrorActivity) MaterialAlertDialogBuilder(this@ErrorActivity)
.setTitle(R.string.customactivityoncrash_error_activity_error_details_title) .setTitle(R.string.customactivityoncrash_error_activity_error_details_title)
.setMessage( .setMessage(
CustomActivityOnCrash.getAllErrorDetailsFromIntent( CustomActivityOnCrash.getAllErrorDetailsFromIntent(
@ -58,13 +58,13 @@ class ErrorActivity : AppCompatActivity() {
val bugReport = createFile( val bugReport = createFile(
context = this, context = this,
"Bug Report", "Bug Report",
"$ReportPrefix${dayFormat.format(Date())}", "$reportPrefix${dayFormat.format(Date())}",
CustomActivityOnCrash.getAllErrorDetailsFromIntent( CustomActivityOnCrash.getAllErrorDetailsFromIntent(
this@ErrorActivity, this@ErrorActivity,
intent intent
), ".txt" ), ".txt"
) )
shareFile(this, bugReport) shareFile(this, bugReport, "text/*")
} }
.show() .show()
} }

View file

@ -15,18 +15,16 @@
package code.name.monkey.retromusic.activities package code.name.monkey.retromusic.activities
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore import android.provider.MediaStore
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.contains import androidx.navigation.contains
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsCastActivity import code.name.monkey.retromusic.activities.base.AbsCastActivity
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.fragments.settings.OnThemeChangedListener
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SearchQueryHelper.getSongs import code.name.monkey.retromusic.helper.SearchQueryHelper.getSongs
import code.name.monkey.retromusic.interfaces.IScrollHelper import code.name.monkey.retromusic.interfaces.IScrollHelper
@ -36,20 +34,17 @@ import code.name.monkey.retromusic.repository.PlaylistSongsLoader
import code.name.monkey.retromusic.service.MusicService 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 code.name.monkey.retromusic.util.logE
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.android.ext.android.get import org.koin.android.ext.android.get
class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener { class MainActivity : AbsCastActivity(), OnThemeChangedListener {
companion object { companion object {
const val TAG = "MainActivity" const val TAG = "MainActivity"
const val EXPAND_PANEL = "expand_panel" const val EXPAND_PANEL = "expand_panel"
} }
override fun createContentView(): SlidingMusicPanelLayoutBinding {
return wrapSlidingMusicPanel()
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setTaskDescriptionColorAuto() setTaskDescriptionColorAuto()
@ -58,9 +53,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
AppRater.appLaunched(this) AppRater.appLaunched(this)
setupNavigationController() setupNavigationController()
if (!hasPermissions()) {
findNavController(R.id.fragment_container).navigate(R.id.permissionFragment)
}
WhatsNewFragment.showChangeLog(this) WhatsNewFragment.showChangeLog(this)
} }
@ -137,20 +130,18 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
} }
} }
override fun onResume() { override fun onThemeValuesChanged() {
super.onResume() restart()
PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
} }
override fun onDestroy() { private fun restart() {
super.onDestroy() val savedInstanceState = Bundle().apply {
PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this) onSaveInstanceState(this)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == GENERAL_THEME || key == MATERIAL_YOU || key == WALLPAPER_ACCENT || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES || key == CUSTOM_FONT || key == APPBAR_MODE || key == CIRCLE_PLAY_BUTTON || key == SWIPE_DOWN_DISMISS) {
postRecreate()
} }
finish()
val intent = Intent(this, this::class.java).putExtra(TAG, savedInstanceState)
startActivity(intent)
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
} }
override fun onServiceConnected() { override fun onServiceConnected() {
@ -220,7 +211,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
private fun parseLongFromIntent( private fun parseLongFromIntent(
intent: Intent, intent: Intent,
longKey: String, longKey: String,
stringKey: String stringKey: String,
): Long { ): Long {
var id = intent.getLongExtra(longKey, -1) var id = intent.getLongExtra(longKey, -1)
if (id < 0) { if (id < 0) {
@ -229,7 +220,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
try { try {
id = idString.toLong() id = idString.toLong()
} catch (e: NumberFormatException) { } catch (e: NumberFormatException) {
println(e.message) logE(e)
} }
} }
} }

View file

@ -63,7 +63,7 @@ class PermissionActivity : AbsMusicServiceActivity() {
binding.bluetoothPermission.setButtonClick { binding.bluetoothPermission.setButtonClick {
ActivityCompat.requestPermissions(this, ActivityCompat.requestPermissions(this,
arrayOf(BLUETOOTH_CONNECT), arrayOf(BLUETOOTH_CONNECT),
PERMISSION_REQUEST) BLUETOOTH_PERMISSION_REQUEST)
} }
} }

View file

@ -24,7 +24,7 @@ import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.BuildConfig import code.name.monkey.retromusic.BuildConfig
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
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.AbsThemeActivity
import code.name.monkey.retromusic.databinding.ActivityProVersionBinding import code.name.monkey.retromusic.databinding.ActivityProVersionBinding
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.setLightStatusBar import code.name.monkey.retromusic.extensions.setLightStatusBar
@ -33,7 +33,7 @@ import code.name.monkey.retromusic.extensions.showToast
import com.anjlab.android.iab.v3.BillingProcessor import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.PurchaseInfo import com.anjlab.android.iab.v3.PurchaseInfo
class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler { class PurchaseActivity : AbsThemeActivity(), BillingProcessor.IBillingHandler {
private lateinit var binding: ActivityProVersionBinding private lateinit var binding: ActivityProVersionBinding
private lateinit var billingProcessor: BillingProcessor private lateinit var billingProcessor: BillingProcessor

View file

@ -25,7 +25,7 @@ import androidx.core.net.toUri
import androidx.core.view.drawToBitmap import androidx.core.view.drawToBitmap
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.activities.base.AbsBaseActivity import code.name.monkey.retromusic.activities.base.AbsThemeActivity
import code.name.monkey.retromusic.databinding.ActivityShareInstagramBinding import code.name.monkey.retromusic.databinding.ActivityShareInstagramBinding
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.setLightStatusBar import code.name.monkey.retromusic.extensions.setLightStatusBar
@ -41,7 +41,7 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
* Created by hemanths on 2020-02-02. * Created by hemanths on 2020-02-02.
*/ */
class ShareInstagramStory : AbsBaseActivity() { class ShareInstagramStory : AbsThemeActivity() {
private lateinit var binding: ActivityShareInstagramBinding private lateinit var binding: ActivityShareInstagramBinding

View file

@ -30,7 +30,7 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.BuildConfig import code.name.monkey.retromusic.BuildConfig
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.AbsThemeActivity
import code.name.monkey.retromusic.databinding.ActivityDonationBinding import code.name.monkey.retromusic.databinding.ActivityDonationBinding
import code.name.monkey.retromusic.databinding.ItemDonationOptionBinding import code.name.monkey.retromusic.databinding.ItemDonationOptionBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.*
@ -38,7 +38,7 @@ import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.PurchaseInfo import com.anjlab.android.iab.v3.PurchaseInfo
import com.anjlab.android.iab.v3.SkuDetails import com.anjlab.android.iab.v3.SkuDetails
class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler { class SupportDevelopmentActivity : AbsThemeActivity(), BillingProcessor.IBillingHandler {
lateinit var binding: ActivityDonationBinding lateinit var binding: ActivityDonationBinding
@ -91,8 +91,7 @@ class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingH
private fun loadSkuDetails() { private fun loadSkuDetails() {
binding.progressContainer.isVisible = true binding.progressContainer.isVisible = true
binding.recyclerView.isVisible = false binding.recyclerView.isVisible = false
val ids = val ids = resources.getStringArray(DONATION_PRODUCT_IDS)
resources.getStringArray(DONATION_PRODUCT_IDS)
billingProcessor!!.getPurchaseListingDetailsAsync( billingProcessor!!.getPurchaseListingDetailsAsync(
ArrayList(listOf(*ids)), ArrayList(listOf(*ids)),
object : BillingProcessor.ISkuDetailsResponseListener { object : BillingProcessor.ISkuDetailsResponseListener {
@ -139,7 +138,7 @@ class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingH
class SkuDetailsAdapter( class SkuDetailsAdapter(
private var donationsDialog: SupportDevelopmentActivity, private var donationsDialog: SupportDevelopmentActivity,
objects: List<SkuDetails> objects: List<SkuDetails>,
) : RecyclerView.Adapter<SkuDetailsAdapter.ViewHolder>() { ) : RecyclerView.Adapter<SkuDetailsAdapter.ViewHolder>() {
private var skuDetailsList: List<SkuDetails> = ArrayList() private var skuDetailsList: List<SkuDetails> = ArrayList()
@ -175,7 +174,7 @@ class SkuDetailsAdapter(
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
val skuDetails = skuDetailsList[i] val skuDetails = skuDetailsList[i]
with(viewHolder.binding) { with(viewHolder.binding) {
itemTitle.text = skuDetails.title.replace("Music Player - MP3 Player - Retro", "") itemTitle.text = skuDetails.title.replace("Retro Music Player MP3 Player", "")
.trim { it <= ' ' } .trim { it <= ' ' }
itemText.text = skuDetails.description itemText.text = skuDetails.description
itemText.isVisible = false itemText.isVisible = false
@ -200,7 +199,7 @@ class SkuDetailsAdapter(
strikeThrough(itemPrice, purchased) strikeThrough(itemPrice, purchased)
} }
viewHolder.itemView.setOnTouchListener { _, _ -> purchased } viewHolder.itemView.isEnabled = !purchased
viewHolder.itemView.setOnClickListener { donationsDialog.donate(i) } viewHolder.itemView.setOnClickListener { donationsDialog.donate(i) }
} }

View file

@ -32,6 +32,8 @@ import androidx.core.content.getSystemService
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.rootView
import code.name.monkey.retromusic.util.logD
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
abstract class AbsBaseActivity : AbsThemeActivity() { abstract class AbsBaseActivity : AbsThemeActivity() {
@ -52,7 +54,7 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
} }
private val snackBarContainer: View private val snackBarContainer: View
get() = window.decorView get() = rootView
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -75,7 +77,7 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
protected open fun onHasPermissionsChanged(hasPermissions: Boolean) { protected open fun onHasPermissionsChanged(hasPermissions: Boolean) {
// implemented by sub classes // implemented by sub classes
println(hasPermissions) logD(hasPermissions)
} }
override fun dispatchKeyEvent(event: KeyEvent): Boolean { override fun dispatchKeyEvent(event: KeyEvent): Boolean {
@ -114,33 +116,19 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
for (grantResult in grantResults) { for (grantResult in grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) { if (grantResult != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale( if (ActivityCompat.shouldShowRequestPermissionRationale(
this@AbsBaseActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE this@AbsBaseActivity, Manifest.permission.READ_EXTERNAL_STORAGE,
) || ActivityCompat.shouldShowRequestPermissionRationale(
this@AbsBaseActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE,
) )
) { ) {
// User has deny from permission dialog // User has deny from permission dialog
Snackbar.make( Snackbar.make(
snackBarContainer, snackBarContainer,
permissionDeniedMessage!!, permissionDeniedMessage!!,
Snackbar.LENGTH_INDEFINITE Snackbar.LENGTH_SHORT
) )
.setAction(R.string.action_grant) { requestPermissions() } .setAction(R.string.action_grant) { requestPermissions() }
.setActionTextColor(accentColor()).show() .setActionTextColor(accentColor()).show()
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
this@AbsBaseActivity, Manifest.permission.BLUETOOTH_CONNECT
)
) {
// User has deny from permission dialog
Snackbar.make(
snackBarContainer,
R.string.permission_bluetooth_denied,
Snackbar.LENGTH_INDEFINITE
)
.setAction(R.string.action_grant) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.BLUETOOTH_CONNECT),
PERMISSION_REQUEST)
}
.setActionTextColor(accentColor()).show()
} else { } else {
// User has deny permission and checked never show permission dialog so you can redirect to Application settings page // User has deny permission and checked never show permission dialog so you can redirect to Application settings page
Snackbar.make( Snackbar.make(
@ -165,11 +153,34 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
} }
hadPermissions = true hadPermissions = true
onHasPermissionsChanged(true) onHasPermissionsChanged(true)
} else if (requestCode == BLUETOOTH_PERMISSION_REQUEST) {
for (grantResult in grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this@AbsBaseActivity, Manifest.permission.BLUETOOTH_CONNECT
)
) {
// User has deny from permission dialog
Snackbar.make(
snackBarContainer,
R.string.permission_bluetooth_denied,
Snackbar.LENGTH_SHORT
)
.setAction(R.string.action_grant) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.BLUETOOTH_CONNECT),
BLUETOOTH_PERMISSION_REQUEST)
}
.setActionTextColor(accentColor()).show()
}
}
}
} }
} }
companion object { companion object {
const val PERMISSION_REQUEST = 100 const val PERMISSION_REQUEST = 100
const val BLUETOOTH_PERMISSION_REQUEST = 101
} }
// this lets keyboard close when clicked in background // this lets keyboard close when clicked in background

View file

@ -1,13 +1,10 @@
package code.name.monkey.retromusic.activities.base package code.name.monkey.retromusic.activities.base
import android.os.Bundle
import code.name.monkey.retromusic.cast.CastHelper
import code.name.monkey.retromusic.cast.RetroSessionManagerListener import code.name.monkey.retromusic.cast.RetroSessionManagerListener
import code.name.monkey.retromusic.cast.RetroWebServer import code.name.monkey.retromusic.cast.RetroWebServer
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import com.google.android.gms.cast.framework.CastContext import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastSession import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManager
import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.GoogleApiAvailability
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
@ -16,10 +13,20 @@ import org.koin.android.ext.android.inject
abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() { abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() {
private var mCastSession: CastSession? = null private var mCastSession: CastSession? = null
private lateinit var sessionManager: SessionManager private val sessionManager by lazy {
CastContext.getSharedInstance(this).sessionManager
}
private val webServer: RetroWebServer by inject() private val webServer: RetroWebServer by inject()
private var playServicesAvailable: Boolean = false private val playServicesAvailable: Boolean by lazy {
try {
GoogleApiAvailability
.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS
} catch (e: Exception) {
false
}
}
private val sessionManagerListener by lazy { private val sessionManagerListener by lazy {
object : RetroSessionManagerListener { object : RetroSessionManagerListener {
@ -30,20 +37,7 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() {
override fun onSessionStarted(castSession: CastSession, p1: String) { override fun onSessionStarted(castSession: CastSession, p1: String) {
invalidateOptionsMenu() invalidateOptionsMenu()
mCastSession = castSession mCastSession = castSession
loadCastQueue() MusicPlayerRemote.switchToRemotePlayback(castSession)
MusicPlayerRemote.isCasting = true
setAllowDragging(false)
collapsePanel()
}
override fun onSessionEnding(castSession: CastSession) {
MusicPlayerRemote.isCasting = false
castSession.remoteMediaClient?.let {
val position = it.mediaQueue.indexOfItemWithId(it.currentItem?.itemId ?: 0)
val progress = it.approximateStreamPosition
MusicPlayerRemote.position = position
MusicPlayerRemote.seekTo(progress.toInt())
}
} }
override fun onSessionEnded(castSession: CastSession, p1: Int) { override fun onSessionEnded(castSession: CastSession, p1: Int) {
@ -51,7 +45,7 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() {
if (mCastSession == castSession) { if (mCastSession == castSession) {
mCastSession = null mCastSession = null
} }
setAllowDragging(true) MusicPlayerRemote.switchToLocalPlayback()
webServer.stop() webServer.stop()
} }
@ -59,14 +53,7 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() {
invalidateOptionsMenu() invalidateOptionsMenu()
mCastSession = castSession mCastSession = castSession
webServer.start() webServer.start()
mCastSession?.remoteMediaClient?.let { MusicPlayerRemote.switchToRemotePlayback(castSession)
loadCastQueue(it.mediaQueue.indexOfItemWithId(it.currentItem?.itemId ?: 0),
it.approximateStreamPosition)
}
MusicPlayerRemote.isCasting = true
setAllowDragging(false)
collapsePanel()
} }
override fun onSessionSuspended(castSession: CastSession, p1: Int) { override fun onSessionSuspended(castSession: CastSession, p1: Int) {
@ -74,30 +61,12 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() {
if (mCastSession == castSession) { if (mCastSession == castSession) {
mCastSession = null mCastSession = null
} }
MusicPlayerRemote.isCasting = false MusicPlayerRemote.switchToLocalPlayback()
setAllowDragging(true)
webServer.stop() webServer.stop()
} }
} }
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
playServicesAvailable = try {
GoogleApiAvailability
.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS
} catch (e: Exception) {
false
}
if (playServicesAvailable) {
setupCast()
}
}
private fun setupCast() {
sessionManager = CastContext.getSharedInstance(this).sessionManager
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (playServicesAvailable) { if (playServicesAvailable) {
@ -121,27 +90,4 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() {
mCastSession = null mCastSession = null
} }
} }
fun loadCastQueue(
position: Int = MusicPlayerRemote.position,
progress: Long = MusicPlayerRemote.songProgressMillis.toLong(),
) {
mCastSession?.let {
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
CastHelper.castQueue(
it,
MusicPlayerRemote.playingQueue,
position,
progress
)
}
}
}
override fun onQueueChanged() {
super.onQueueChanged()
if (playServicesAvailable) {
loadCastQueue()
}
}
} }

View file

@ -33,6 +33,7 @@ import code.name.monkey.retromusic.service.MusicService.Companion.QUEUE_CHANGED
import code.name.monkey.retromusic.service.MusicService.Companion.REPEAT_MODE_CHANGED import code.name.monkey.retromusic.service.MusicService.Companion.REPEAT_MODE_CHANGED
import code.name.monkey.retromusic.service.MusicService.Companion.SHUFFLE_MODE_CHANGED import code.name.monkey.retromusic.service.MusicService.Companion.SHUFFLE_MODE_CHANGED
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.logD
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
@ -185,7 +186,7 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventLi
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)
println("sendBroadcast $hasPermissions") logD("sendBroadcast $hasPermissions")
} }
override fun getPermissionsToRequest(): Array<String> { override fun getPermissionsToRequest(): Array<String> {

View file

@ -16,6 +16,8 @@ package code.name.monkey.retromusic.activities.base
import android.animation.ArgbEvaluator import android.animation.ArgbEvaluator
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
@ -25,11 +27,14 @@ import android.view.ViewTreeObserver
import android.view.animation.PathInterpolator import android.view.animation.PathInterpolator
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.animation.doOnEnd import androidx.core.animation.doOnEnd
import androidx.core.view.* import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.commit import androidx.fragment.app.commit
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.activities.PermissionActivity
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
@ -60,12 +65,14 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.CategoryInfo import code.name.monkey.retromusic.model.CategoryInfo
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil import code.name.monkey.retromusic.util.ViewUtil
import code.name.monkey.retromusic.util.logD
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.* import com.google.android.material.bottomsheet.BottomSheetBehavior.*
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() { abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
SharedPreferences.OnSharedPreferenceChangeListener {
companion object { companion object {
val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName
} }
@ -74,13 +81,13 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
private var windowInsets: WindowInsetsCompat? = null private var windowInsets: WindowInsetsCompat? = null
protected val libraryViewModel by viewModel<LibraryViewModel>() protected val libraryViewModel by viewModel<LibraryViewModel>()
private lateinit var bottomSheetBehavior: BottomSheetBehavior<FrameLayout> private lateinit var bottomSheetBehavior: BottomSheetBehavior<FrameLayout>
private var playerFragment: AbsPlayerFragment? = null private lateinit var playerFragment: AbsPlayerFragment
private var miniPlayerFragment: MiniPlayerFragment? = null private var miniPlayerFragment: MiniPlayerFragment? = null
private var nowPlayingScreen: NowPlayingScreen? = null private var nowPlayingScreen: NowPlayingScreen? = null
private var taskColor: Int = 0 private var taskColor: Int = 0
private var paletteColor: Int = Color.WHITE private var paletteColor: Int = Color.WHITE
private var navigationBarColor = 0 private var navigationBarColor = 0
protected abstract fun createContentView(): SlidingMusicPanelLayoutBinding
private val panelState: Int private val panelState: Int
get() = bottomSheetBehavior.state get() = bottomSheetBehavior.state
private lateinit var binding: SlidingMusicPanelLayoutBinding private lateinit var binding: SlidingMusicPanelLayoutBinding
@ -89,7 +96,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
private var navigationBarColorAnimator: ValueAnimator? = null private var navigationBarColorAnimator: ValueAnimator? = null
private val argbEvaluator: ArgbEvaluator = ArgbEvaluator() private val argbEvaluator: ArgbEvaluator = ArgbEvaluator()
private val bottomSheetCallbackList = object : BottomSheetCallback() { private val bottomSheetCallbackList by lazy {
object : BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) { override fun onSlide(bottomSheet: View, slideOffset: Float) {
setMiniPlayerAlphaProgress(slideOffset) setMiniPlayerAlphaProgress(slideOffset)
@ -127,7 +135,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
MusicPlayerRemote.clearQueue() MusicPlayerRemote.clearQueue()
} }
else -> { else -> {
println("Do a flip") logD("Do a flip")
}
} }
} }
} }
@ -137,12 +146,14 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = createContentView() if (!hasPermissions()) {
startActivity(Intent(this, PermissionActivity::class.java))
finish()
}
binding = SlidingMusicPanelLayoutBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener( binding.root.setOnApplyWindowInsetsListener { _, insets ->
binding.root windowInsets = WindowInsetsCompat.toWindowInsetsCompat(insets)
) { _, insets ->
windowInsets = insets
insets insets
} }
chooseFragmentForTheme() chooseFragmentForTheme()
@ -166,6 +177,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
if (nowPlayingScreen != PreferenceUtil.nowPlayingScreen) { if (nowPlayingScreen != PreferenceUtil.nowPlayingScreen) {
postRecreate() postRecreate()
} }
@ -177,10 +189,49 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallbackList) bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallbackList)
PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this)
} }
protected fun wrapSlidingMusicPanel(): SlidingMusicPanelLayoutBinding { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
return SlidingMusicPanelLayoutBinding.inflate(layoutInflater) when (key) {
SWIPE_DOWN_DISMISS -> {
bottomSheetBehavior.isHideable = PreferenceUtil.swipeDownToDismiss
}
TOGGLE_ADD_CONTROLS -> {
miniPlayerFragment?.setUpButtons()
}
NOW_PLAYING_SCREEN_ID, ALBUM_COVER_TRANSFORM, CAROUSEL_EFFECT,
ALBUM_COVER_STYLE, TOGGLE_VOLUME, EXTRA_SONG_INFO, CIRCLE_PLAY_BUTTON,
-> {
chooseFragmentForTheme()
onServiceConnected()
}
SWIPE_ANYWHERE_NOW_PLAYING -> {
playerFragment.addSwipeDetector()
}
ADAPTIVE_COLOR_APP -> {
if (PreferenceUtil.nowPlayingScreen in listOf(Normal, Material, Flat)) {
chooseFragmentForTheme()
onServiceConnected()
}
}
LIBRARY_CATEGORIES -> {
updateTabs()
}
TAB_TEXT_MODE -> {
bottomNavigationView.labelVisibilityMode = PreferenceUtil.tabTitleMode
}
TOGGLE_FULL_SCREEN -> {
if (!PreferenceUtil.isFullScreenMode) exitFullscreen()
setEdgeToEdgeOrImmersive()
}
SCREEN_ON_LYRICS -> {
keepScreenOn(bottomSheetBehavior.state == STATE_EXPANDED && PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics || PreferenceUtil.isScreenOnEnabled)
}
KEEP_SCREEN_ON -> {
maybeSetScreenOn()
}
}
} }
fun collapsePanel() { fun collapsePanel() {
@ -224,13 +275,13 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
setLightStatusBarAuto() setLightStatusBarAuto()
setLightNavigationBarAuto() setLightNavigationBarAuto()
setTaskDescriptionColor(taskColor) setTaskDescriptionColor(taskColor)
playerFragment?.onHide() //playerFragment?.onHide()
} }
open fun onPanelExpanded() { open fun onPanelExpanded() {
setMiniPlayerAlphaProgress(1F) setMiniPlayerAlphaProgress(1F)
onPaletteColorChanged() onPaletteColorChanged()
playerFragment?.onShow() //playerFragment?.onShow()
} }
private fun setupSlidingUpPanel() { private fun setupSlidingUpPanel() {
@ -260,16 +311,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
override fun onServiceConnected() { override fun onServiceConnected() {
super.onServiceConnected() super.onServiceConnected()
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
binding.slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
binding.slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
hideBottomSheet(false) hideBottomSheet(false)
} }
})
} // don't call hideBottomSheet(true) here as it causes a bug with the SlidingUpPanelLayout
}
override fun onQueueChanged() { override fun onQueueChanged() {
super.onQueueChanged() super.onQueueChanged()
@ -285,7 +328,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} }
private fun handleBackPress(): Boolean { private fun handleBackPress(): Boolean {
if (bottomSheetBehavior.peekHeight != 0 && playerFragment!!.onBackPressed()) return true if (bottomSheetBehavior.peekHeight != 0 && playerFragment.onBackPressed()) return true
if (panelState == STATE_EXPANDED) { if (panelState == STATE_EXPANDED) {
collapsePanel() collapsePanel()
return true return true
@ -343,7 +386,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} }
if (binding.bottomNavigationView.menu.size() == 1) { if (binding.bottomNavigationView.menu.size() == 1) {
isInOneTabMode = true isInOneTabMode = true
binding.bottomNavigationView.hide() binding.bottomNavigationView.isVisible = false
} }
} }
@ -367,6 +410,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
) )
return return
} }
if (visible xor bottomNavigationView.isVisible) {
val mAnimate = animate && bottomSheetBehavior.state == STATE_COLLAPSED val mAnimate = animate && bottomSheetBehavior.state == STATE_COLLAPSED
if (mAnimate) { if (mAnimate) {
if (visible) { if (visible) {
@ -381,6 +425,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
binding.bottomNavigationView.bringToFront() binding.bottomNavigationView.bringToFront()
} }
} }
}
hideBottomSheet( hideBottomSheet(
hide = hideBottomSheet, hide = hideBottomSheet,
animate = animate, animate = animate,
@ -393,12 +438,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
animate: Boolean = false, animate: Boolean = false,
isBottomNavVisible: Boolean = bottomNavigationView.isVisible, isBottomNavVisible: Boolean = bottomNavigationView.isVisible,
) { ) {
val heightOfBar = val heightOfBar = windowInsets.getBottomInsets() + dip(R.dimen.mini_player_height)
windowInsets.safeGetBottomInsets() +
if (MusicPlayerRemote.isCasting) dip(R.dimen.cast_mini_player_height) else dip(R.dimen.mini_player_height)
val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height) val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height)
if (hide) { if (hide) {
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets() bottomSheetBehavior.peekHeight = -windowInsets.getBottomInsets()
bottomSheetBehavior.state = STATE_COLLAPSED bottomSheetBehavior.state = STATE_COLLAPSED
libraryViewModel.setFabMargin( libraryViewModel.setFabMargin(
this, this,
@ -409,7 +452,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
binding.slidingPanel.elevation = 0F binding.slidingPanel.elevation = 0F
binding.bottomNavigationView.elevation = 5F binding.bottomNavigationView.elevation = 5F
if (isBottomNavVisible) { if (isBottomNavVisible) {
println("List") logD("List")
if (animate) { if (animate) {
bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs) bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs)
} else { } else {
@ -417,7 +460,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} }
libraryViewModel.setFabMargin(this, dip(R.dimen.mini_player_height_expanded)) libraryViewModel.setFabMargin(this, dip(R.dimen.mini_player_height_expanded))
} else { } else {
println("Details") logD("Details")
if (animate) { if (animate) {
bottomSheetBehavior.peekHeightAnimate(heightOfBar).doOnEnd { bottomSheetBehavior.peekHeightAnimate(heightOfBar).doOnEnd {
binding.slidingPanel.bringToFront() binding.slidingPanel.bringToFront()
@ -440,7 +483,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
private fun chooseFragmentForTheme() { private fun chooseFragmentForTheme() {
nowPlayingScreen = PreferenceUtil.nowPlayingScreen nowPlayingScreen = PreferenceUtil.nowPlayingScreen
val fragment: Fragment = when (nowPlayingScreen) { val fragment: AbsPlayerFragment = when (nowPlayingScreen) {
Blur -> BlurPlayerFragment() Blur -> BlurPlayerFragment()
Adaptive -> AdaptiveFragment() Adaptive -> AdaptiveFragment()
Normal -> PlayerFragment() Normal -> PlayerFragment()
@ -460,12 +503,12 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
Classic -> ClassicPlayerFragment() Classic -> ClassicPlayerFragment()
MD3 -> MD3PlayerFragment() MD3 -> MD3PlayerFragment()
else -> PlayerFragment() else -> PlayerFragment()
} // must implement AbsPlayerFragment } // must extend AbsPlayerFragment
supportFragmentManager.commit { supportFragmentManager.commit {
replace(R.id.playerFragmentContainer, fragment) replace(R.id.playerFragmentContainer, fragment)
} }
supportFragmentManager.executePendingTransactions() supportFragmentManager.executePendingTransactions()
playerFragment = whichFragment<AbsPlayerFragment>(R.id.playerFragmentContainer) playerFragment = whichFragment(R.id.playerFragmentContainer)
miniPlayerFragment = whichFragment<MiniPlayerFragment>(R.id.miniPlayerFragment) miniPlayerFragment = whichFragment<MiniPlayerFragment>(R.id.miniPlayerFragment)
miniPlayerFragment?.view?.setOnClickListener { expandPanel() } miniPlayerFragment?.view?.setOnClickListener { expandPanel() }
} }

View file

@ -20,7 +20,6 @@ import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
import androidx.core.os.ConfigurationCompat import androidx.core.os.ConfigurationCompat
import code.name.monkey.appthemehelper.common.ATHToolbarActivity import code.name.monkey.appthemehelper.common.ATHToolbarActivity
@ -29,6 +28,7 @@ import code.name.monkey.retromusic.LanguageContextWrapper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.maybeShowAnnoyingToasts
import code.name.monkey.retromusic.util.theme.getNightMode import code.name.monkey.retromusic.util.theme.getNightMode
import code.name.monkey.retromusic.util.theme.getThemeResValue import code.name.monkey.retromusic.util.theme.getThemeResValue
import com.google.android.play.core.splitcompat.SplitCompat import com.google.android.play.core.splitcompat.SplitCompat
@ -42,14 +42,15 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
updateTheme() updateTheme()
hideStatusBar() hideStatusBar()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
println("OnCreate")
setEdgeToEdgeOrImmersive() setEdgeToEdgeOrImmersive()
registerSystemUiVisibility() maybeSetScreenOn()
toggleScreenOn()
setLightNavigationBarAuto() setLightNavigationBarAuto()
setLightStatusBarAuto(surfaceColor()) setLightStatusBarAuto(surfaceColor())
if (VersionUtils.hasQ()) { if (VersionUtils.hasQ()) {
window.decorView.isForceDarkAllowed = false window.decorView.isForceDarkAllowed = false
} }
maybeShowAnnoyingToasts()
} }
private fun updateTheme() { private fun updateTheme() {
@ -61,9 +62,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
if (PreferenceUtil.isCustomFont) { if (PreferenceUtil.isCustomFont) {
setTheme(R.style.FontThemeOverlay) setTheme(R.style.FontThemeOverlay)
} }
if (PreferenceUtil.circlePlayButton) {
setTheme(R.style.CircleFABOverlay)
}
} }
override fun onWindowFocusChanged(hasFocus: Boolean) { override fun onWindowFocusChanged(hasFocus: Boolean) {
@ -77,20 +75,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
} }
} }
private fun registerSystemUiVisibility() {
val decorView = window.decorView
decorView.setOnSystemUiVisibilityChangeListener { visibility ->
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
setImmersiveFullscreen()
}
}
}
private fun unregisterSystemUiVisibility() {
val decorView = window.decorView
decorView.setOnSystemUiVisibilityChangeListener(null)
}
override fun run() { override fun run() {
setImmersiveFullscreen() setImmersiveFullscreen()
} }
@ -102,7 +86,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
public override fun onDestroy() { public override fun onDestroy() {
super.onDestroy() super.onDestroy()
unregisterSystemUiVisibility()
exitFullscreen() exitFullscreen()
} }

View file

@ -33,8 +33,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.R.drawable import code.name.monkey.retromusic.R.drawable
@ -48,6 +46,7 @@ import code.name.monkey.retromusic.model.ArtworkInfo
import code.name.monkey.retromusic.model.AudioTagInfo import code.name.monkey.retromusic.model.AudioTagInfo
import code.name.monkey.retromusic.repository.Repository import code.name.monkey.retromusic.repository.Repository
import code.name.monkey.retromusic.util.SAFUtil import code.name.monkey.retromusic.util.SAFUtil
import code.name.monkey.retromusic.util.logD
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -223,7 +222,7 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
getIntentExtras() getIntentExtras()
songPaths = getSongPaths() songPaths = getSongPaths()
println(songPaths?.size) logD(songPaths?.size)
if (songPaths!!.isEmpty()) { if (songPaths!!.isEmpty()) {
finish() finish()
} }
@ -276,7 +275,6 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
scaleY = 0f scaleY = 0f
isEnabled = false isEnabled = false
setOnClickListener { save() } setOnClickListener { save() }
TintHelper.setTintAuto(this, ThemeStore.accentColor(this@AbsTagEditorActivity), true)
} }
} }
@ -352,7 +350,7 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
hideSoftKeyboard() hideSoftKeyboard()
hideFab() hideFab()
println(fieldKeyValueMap) logD(fieldKeyValueMap)
GlobalScope.launch { GlobalScope.launch {
if (VersionUtils.hasR()) { if (VersionUtils.hasR()) {
cacheFiles = TagWriter.writeTagsToFilesR( cacheFiles = TagWriter.writeTagsToFilesR(

View file

@ -39,6 +39,7 @@ import code.name.monkey.retromusic.util.ImageUtil
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroColorUtil.generatePalette import code.name.monkey.retromusic.util.RetroColorUtil.generatePalette
import code.name.monkey.retromusic.util.RetroColorUtil.getColor import code.name.monkey.retromusic.util.RetroColorUtil.getColor
import code.name.monkey.retromusic.util.logD
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.target.ImageViewTarget import com.bumptech.glide.request.target.ImageViewTarget
import com.bumptech.glide.request.transition.Transition import com.bumptech.glide.request.transition.Transition
@ -98,7 +99,7 @@ class AlbumTagEditorActivity : AbsTagEditorActivity<ActivityAlbumTagEditorBindin
binding.albumArtistText.setText(albumArtistName) binding.albumArtistText.setText(albumArtistName)
binding.genreTitle.setText(genreName) binding.genreTitle.setText(genreName)
binding.yearTitle.setText(songYear) binding.yearTitle.setText(songYear)
println(albumTitle + albumArtistName) logD(albumTitle + albumArtistName)
} }
override fun loadCurrentImage() { override fun loadCurrentImage() {

View file

@ -38,6 +38,7 @@ import code.name.monkey.retromusic.repository.SongRepository
import code.name.monkey.retromusic.util.ImageUtil import code.name.monkey.retromusic.util.ImageUtil
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroColorUtil import code.name.monkey.retromusic.util.RetroColorUtil
import code.name.monkey.retromusic.util.logD
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.target.ImageViewTarget import com.bumptech.glide.request.target.ImageViewTarget
import com.bumptech.glide.request.transition.Transition import com.bumptech.glide.request.transition.Transition
@ -102,7 +103,7 @@ class SongTagEditorActivity : AbsTagEditorActivity<ActivitySongTagEditorBinding>
binding.discNumberText.setText(discNumber) binding.discNumberText.setText(discNumber)
binding.lyricsText.setText(lyrics) binding.lyricsText.setText(lyrics)
binding.songComposerText.setText(composer) binding.songComposerText.setText(composer)
println(songTitle + songYear) logD(songTitle + songYear)
} }
override fun loadCurrentImage() { override fun loadCurrentImage() {

View file

@ -18,7 +18,6 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
@ -35,14 +34,14 @@ import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.fragments.home.HomeFragment import code.name.monkey.retromusic.fragments.home.HomeFragment
import code.name.monkey.retromusic.interfaces.IAlbumClickListener import code.name.monkey.retromusic.interfaces.IAlbumClickListener
import code.name.monkey.retromusic.interfaces.IArtistClickListener import code.name.monkey.retromusic.interfaces.IArtistClickListener
import code.name.monkey.retromusic.interfaces.IGenreClickListener import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Home
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
class HomeAdapter( class HomeAdapter(private val activity: AppCompatActivity) :
private val activity: AppCompatActivity RecyclerView.Adapter<RecyclerView.ViewHolder>(), IArtistClickListener, IAlbumClickListener {
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IArtistClickListener, IAlbumClickListener,
IGenreClickListener {
private var list = listOf<Home>() private var list = listOf<Home>()
@ -134,6 +133,7 @@ class HomeAdapter(
notifyDataSetChanged() notifyDataSetChanged()
} }
@Suppress("UNCHECKED_CAST")
private inner class AlbumViewHolder(view: View) : AbsHomeViewItem(view) { private inner class AlbumViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(home: Home) { fun bindView(home: Home) {
title.setText(home.titleRes) title.setText(home.titleRes)
@ -144,6 +144,7 @@ class HomeAdapter(
} }
} }
@Suppress("UNCHECKED_CAST")
private inner class ArtistViewHolder(view: View) : AbsHomeViewItem(view) { private inner class ArtistViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(home: Home) { fun bindView(home: Home) {
title.setText(home.titleRes) title.setText(home.titleRes)
@ -154,6 +155,7 @@ class HomeAdapter(
} }
} }
@Suppress("UNCHECKED_CAST")
private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) { private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(home: Home) { fun bindView(home: Home) {
title.setText(home.titleRes) title.setText(home.titleRes)
@ -172,7 +174,6 @@ class HomeAdapter(
open class AbsHomeViewItem(itemView: View) : RecyclerView.ViewHolder(itemView) { open class AbsHomeViewItem(itemView: View) : RecyclerView.ViewHolder(itemView) {
val recyclerView: RecyclerView = itemView.findViewById(R.id.recyclerView) val recyclerView: RecyclerView = itemView.findViewById(R.id.recyclerView)
val title: AppCompatTextView = itemView.findViewById(R.id.title) val title: AppCompatTextView = itemView.findViewById(R.id.title)
val arrow: ImageView = itemView.findViewById(R.id.arrow)
val clickableArea: ViewGroup = itemView.findViewById(R.id.clickable_area) val clickableArea: ViewGroup = itemView.findViewById(R.id.clickable_area)
} }
@ -209,16 +210,4 @@ class HomeAdapter(
) )
) )
} }
override fun onClickGenre(genre: Genre, view: View) {
activity.findNavController(R.id.fragment_container).navigate(
R.id.genreDetailsFragment,
bundleOf(EXTRA_GENRE to genre),
null,
FragmentNavigatorExtras(
view to "genre"
)
)
}
} }

View file

@ -89,7 +89,7 @@ class AppWidgetCircle : BaseAppWidget() {
).toBitmap() ).toBitmap()
) )
val isFavorite = runBlocking(Dispatchers.IO) { val isFavorite = runBlocking(Dispatchers.IO) {
return@runBlocking MusicUtil.repository.isSongFavorite(song.id) return@runBlocking MusicUtil.isFavorite(song)
} }
val favoriteRes = val favoriteRes =
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border

View file

@ -6,12 +6,11 @@ import code.name.monkey.retromusic.cast.RetroWebServer.Companion.PART_COVER_ART
import code.name.monkey.retromusic.cast.RetroWebServer.Companion.PART_SONG import code.name.monkey.retromusic.cast.RetroWebServer.Companion.PART_SONG
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil
import com.google.android.gms.cast.* import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaInfo.STREAM_TYPE_BUFFERED import com.google.android.gms.cast.MediaInfo.STREAM_TYPE_BUFFERED
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.cast.MediaMetadata.* import com.google.android.gms.cast.MediaMetadata.*
import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.common.images.WebImage import com.google.android.gms.common.images.WebImage
import org.json.JSONObject
import java.net.MalformedURLException import java.net.MalformedURLException
import java.net.URL import java.net.URL
@ -21,39 +20,7 @@ object CastHelper {
private const val CAST_MUSIC_METADATA_ALBUM_ID = "metadata_album_id" private const val CAST_MUSIC_METADATA_ALBUM_ID = "metadata_album_id"
private const val CAST_URL_PROTOCOL = "http" private const val CAST_URL_PROTOCOL = "http"
fun castSong(castSession: CastSession, song: Song) { fun Song.toMediaInfo(): MediaInfo? {
try {
val remoteMediaClient = castSession.remoteMediaClient
val mediaLoadOptions = MediaLoadOptions.Builder().apply {
setPlayPosition(0)
setAutoplay(true)
}.build()
remoteMediaClient?.load(song.toMediaInfo()!!, mediaLoadOptions)
} catch (e: Exception) {
e.printStackTrace()
}
}
fun castQueue(castSession: CastSession, songs: List<Song>, position: Int, progress: Long) {
try {
val remoteMediaClient = castSession.remoteMediaClient
remoteMediaClient?.queueLoad(
songs.toMediaInfoList(),
if (position != -1) position else 0,
MediaStatus.REPEAT_MODE_REPEAT_OFF,
progress,
JSONObject()
)
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun List<Song>.toMediaInfoList(): Array<MediaQueueItem> {
return map { MediaQueueItem.Builder(it.toMediaInfo()!!).build() }.toTypedArray()
}
private fun Song.toMediaInfo(): MediaInfo? {
val song = this val song = this
val baseUrl: URL val baseUrl: URL
try { try {

View file

@ -3,6 +3,7 @@
package code.name.monkey.retromusic.cast package code.name.monkey.retromusic.cast
import android.content.Context import android.content.Context
import code.name.monkey.retromusic.activities.MainActivity
import com.google.android.gms.cast.CastMediaControlIntent import com.google.android.gms.cast.CastMediaControlIntent
import com.google.android.gms.cast.framework.CastOptions import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.OptionsProvider import com.google.android.gms.cast.framework.OptionsProvider
@ -22,12 +23,12 @@ class CastOptionsProvider : OptionsProvider {
val compatButtonActionsIndices = intArrayOf(1, 3) val compatButtonActionsIndices = intArrayOf(1, 3)
val notificationOptions = NotificationOptions.Builder() val notificationOptions = NotificationOptions.Builder()
.setActions(buttonActions, compatButtonActionsIndices) .setActions(buttonActions, compatButtonActionsIndices)
.setTargetActivityClassName(ExpandedControlsActivity::class.java.name) .setTargetActivityClassName(MainActivity::class.java.name)
.build() .build()
val mediaOptions = CastMediaOptions.Builder() val mediaOptions = CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions) .setNotificationOptions(notificationOptions)
.setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name) .setExpandedControllerActivityClassName(MainActivity::class.java.name)
.build() .build()
return CastOptions.Builder() return CastOptions.Builder()

View file

@ -1,19 +0,0 @@
package code.name.monkey.retromusic.cast
import android.view.Menu
import code.name.monkey.retromusic.R
import com.google.android.gms.cast.framework.CastButtonFactory
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
class ExpandedControlsActivity : ExpandedControllerActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.menu_cast, menu)
CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.action_cast)
return true
}
}

View file

@ -18,14 +18,12 @@ import androidx.room.Database
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
@Database( @Database(
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class, LyricsEntity::class], entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class],
version = 23, version = 24,
exportSchema = false exportSchema = false
) )
abstract class RetroDatabase : RoomDatabase() { abstract class RetroDatabase : RoomDatabase() {
abstract fun playlistDao(): PlaylistDao abstract fun playlistDao(): PlaylistDao
abstract fun blackListStore(): BlackListStoreDao
abstract fun playCountDao(): PlayCountDao abstract fun playCountDao(): PlayCountDao
abstract fun historyDao(): HistoryDao abstract fun historyDao(): HistoryDao
abstract fun lyricsDao(): LyricsDao
} }

View file

@ -0,0 +1,11 @@
package code.name.monkey.retromusic.db
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
val MIGRATION_23_24 = object : Migration(23, 24) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE LyricsEntity")
database.execSQL("DROP TABLE BlackListStoreEntity")
}
}

View file

@ -16,7 +16,7 @@ import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
fun AppCompatActivity.toggleScreenOn() { fun AppCompatActivity.maybeSetScreenOn() {
if (PreferenceUtil.isScreenOnEnabled) { if (PreferenceUtil.isScreenOnEnabled) {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else { } else {

View file

@ -163,6 +163,15 @@ fun SeekBar.applyColor(@ColorInt color: Int) {
progressBackgroundTintList = ColorStateList.valueOf(color) progressBackgroundTintList = ColorStateList.valueOf(color)
} }
fun Slider.applyColor(@ColorInt color: Int) {
ColorStateList.valueOf(color).run {
thumbTintList = this
trackActiveTintList = this
trackInactiveTintList = ColorStateList.valueOf(color.addAlpha(0.1f))
haloTintList = this
}
}
fun ExtendedFloatingActionButton.accentColor() { fun ExtendedFloatingActionButton.accentColor() {
if (materialYou) return if (materialYou) return
val color = ThemeStore.accentColor(context) val color = ThemeStore.accentColor(context)
@ -301,5 +310,9 @@ inline val @receiver:ColorInt Int.lighterColor
inline val @receiver:ColorInt Int.darkerColor inline val @receiver:ColorInt Int.darkerColor
get() = ColorUtil.darkenColor(this) get() = ColorUtil.darkenColor(this)
inline val Int.colorStateList : ColorStateList inline val Int.colorStateList: ColorStateList
get() = ColorStateList.valueOf(this) get() = ColorStateList.valueOf(this)
fun @receiver:ColorInt Int.addAlpha(alpha: Float): Int {
return ColorUtil.withAlpha(this, alpha)
}

View file

@ -4,7 +4,7 @@ import androidx.core.view.WindowInsetsCompat
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil
fun WindowInsetsCompat?.safeGetBottomInsets(): Int { fun WindowInsetsCompat?.getBottomInsets(): Int {
return if (PreferenceUtil.isFullScreenMode) { return if (PreferenceUtil.isFullScreenMode) {
return 0 return 0
} else { } else {

View file

@ -7,14 +7,16 @@ import code.name.monkey.retromusic.util.MusicUtil
val Song.uri get() = MusicUtil.getSongFileUri(songId = id) val Song.uri get() = MusicUtil.getSongFileUri(songId = id)
val Song.albumArtUri get() = MusicUtil.getMediaStoreAlbumCoverUri(albumId)
fun ArrayList<Song>.toMediaSessionQueue(): List<QueueItem> { fun ArrayList<Song>.toMediaSessionQueue(): List<QueueItem> {
return map { return map { song ->
val mediaDescription = MediaDescriptionCompat.Builder() val mediaDescription = MediaDescriptionCompat.Builder()
.setMediaId(it.id.toString()) .setMediaId(song.id.toString())
.setTitle(it.title) .setTitle(song.title)
.setSubtitle(it.artistName) .setSubtitle(song.artistName)
.setIconUri(song.albumArtUri)
.build() .build()
QueueItem(mediaDescription, it.hashCode().toLong()) QueueItem(mediaDescription, song.hashCode().toLong())
} }
} }

View file

@ -40,6 +40,8 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import dev.chrisbanes.insetter.applyInsetter import dev.chrisbanes.insetter.applyInsetter
const val ANIM_DURATION = 300L
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T { fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T {
return LayoutInflater.from(context).inflate(layout, this, false) as T return LayoutInflater.from(context).inflate(layout, this, false) as T
@ -90,10 +92,10 @@ fun BottomNavigationView.show() {
drawable.setBounds(left, parent.height, right, parent.height + height) drawable.setBounds(left, parent.height, right, parent.height + height)
parent.overlay.add(drawable) parent.overlay.add(drawable)
ValueAnimator.ofInt(parent.height, top).apply { ValueAnimator.ofInt(parent.height, top).apply {
duration = 300 duration = ANIM_DURATION
interpolator = AnimationUtils.loadInterpolator( interpolator = AnimationUtils.loadInterpolator(
context, context,
android.R.interpolator.linear_out_slow_in android.R.interpolator.accelerate_decelerate
) )
addUpdateListener { addUpdateListener {
val newTop = it.animatedValue as Int val newTop = it.animatedValue as Int
@ -130,10 +132,10 @@ fun BottomNavigationView.hide() {
parent.overlay.add(drawable) parent.overlay.add(drawable)
isGone = true isGone = true
ValueAnimator.ofInt(top, parent.height).apply { ValueAnimator.ofInt(top, parent.height).apply {
duration = 300L duration = ANIM_DURATION
interpolator = AnimationUtils.loadInterpolator( interpolator = AnimationUtils.loadInterpolator(
context, context,
android.R.interpolator.fast_out_linear_in android.R.interpolator.accelerate_decelerate
) )
addUpdateListener { addUpdateListener {
val newTop = it.animatedValue as Int val newTop = it.animatedValue as Int
@ -164,7 +166,7 @@ fun View.translateYAnimate(value: Float): Animator {
fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int): Animator { fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int): Animator {
return ObjectAnimator.ofInt(this, "peekHeight", value) return ObjectAnimator.ofInt(this, "peekHeight", value)
.apply { .apply {
duration = 300 duration = ANIM_DURATION
start() start()
} }
} }
@ -260,7 +262,7 @@ fun View.updateMargin(
@Px left: Int = marginLeft, @Px left: Int = marginLeft,
@Px top: Int = marginTop, @Px top: Int = marginTop,
@Px right: Int = marginRight, @Px right: Int = marginRight,
@Px bottom: Int = marginBottom @Px bottom: Int = marginBottom,
) { ) {
(layoutParams as ViewGroup.MarginLayoutParams).updateMargins(left, top, right, bottom) (layoutParams as ViewGroup.MarginLayoutParams).updateMargins(left, top, right, bottom)
} }
@ -301,7 +303,7 @@ fun View.requestApplyInsetsWhenAttached() {
data class InitialPadding( data class InitialPadding(
val left: Int, val top: Int, val left: Int, val top: Int,
val right: Int, val bottom: Int val right: Int, val bottom: Int,
) )
fun recordInitialPaddingForView(view: View) = InitialPadding( fun recordInitialPaddingForView(view: View) = InitialPadding(

View file

@ -16,7 +16,6 @@ package code.name.monkey.retromusic.fragments
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.widget.Toast
import androidx.core.animation.doOnEnd import androidx.core.animation.doOnEnd
import androidx.lifecycle.* import androidx.lifecycle.*
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
@ -30,6 +29,7 @@ import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.DensityUtil import code.name.monkey.retromusic.util.DensityUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.logD
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -141,48 +141,47 @@ class LibraryViewModel(
} }
override fun onMediaStoreChanged() { override fun onMediaStoreChanged() {
println("onMediaStoreChanged") logD("onMediaStoreChanged")
loadLibraryContent() loadLibraryContent()
} }
override fun onServiceConnected() { override fun onServiceConnected() {
println("onServiceConnected") logD("onServiceConnected")
} }
override fun onServiceDisconnected() { override fun onServiceDisconnected() {
println("onServiceDisconnected") logD("onServiceDisconnected")
} }
override fun onQueueChanged() { override fun onQueueChanged() {
println("onQueueChanged") logD("onQueueChanged")
} }
override fun onPlayingMetaChanged() { override fun onPlayingMetaChanged() {
println("onPlayingMetaChanged") logD("onPlayingMetaChanged")
} }
override fun onPlayStateChanged() { override fun onPlayStateChanged() {
println("onPlayStateChanged") logD("onPlayStateChanged")
} }
override fun onRepeatModeChanged() { override fun onRepeatModeChanged() {
println("onRepeatModeChanged") logD("onRepeatModeChanged")
} }
override fun onShuffleModeChanged() { override fun onShuffleModeChanged() {
println("onShuffleModeChanged") logD("onShuffleModeChanged")
} }
override fun onFavoriteStateChanged() { override fun onFavoriteStateChanged() {
println("onFavoriteStateChanged") logD("onFavoriteStateChanged")
} }
fun shuffleSongs() = viewModelScope.launch(IO) { fun shuffleSongs() = viewModelScope.launch(IO) {
val songs = repository.allSongs() val songs = repository.allSongs()
MusicPlayerRemote.openAndShuffleQueue( withContext(Main) {
songs, MusicPlayerRemote.openAndShuffleQueue(songs, true)
true }
)
} }
fun renameRoomPlaylist(playListId: Long, name: String) = viewModelScope.launch(IO) { fun renameRoomPlaylist(playListId: Long, name: String) = viewModelScope.launch(IO) {
@ -351,8 +350,7 @@ class LibraryViewModel(
context.getString( context.getString(
R.string.added_song_count_to_playlist, R.string.added_song_count_to_playlist,
songs.size, songs.size,
playlistName), playlistName))
Toast.LENGTH_SHORT)
} }
} }
} }

View file

@ -45,9 +45,9 @@ class MusicSeekSkipTouchListener(val activity: FragmentActivity, val next: Boole
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, event: MotionEvent?): Boolean { override fun onTouch(v: View?, event: MotionEvent?): Boolean {
val action = event?.actionMasked val action = event?.actionMasked
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { if (action == MotionEvent.ACTION_UP) {
job?.cancel() job?.cancel()
if (!wasSeeking) { if (v?.isPressed == true && !wasSeeking) {
if (next) { if (next) {
MusicPlayerRemote.playNextSong() MusicPlayerRemote.playNextSong()
} else { } else {
@ -55,6 +55,8 @@ class MusicSeekSkipTouchListener(val activity: FragmentActivity, val next: Boole
} }
} }
wasSeeking = false wasSeeking = false
} else if (action == MotionEvent.ACTION_CANCEL) {
job?.cancel()
} }
return gestureDetector.onTouchEvent(event) return gestureDetector.onTouchEvent(event)
} }

View file

@ -62,10 +62,7 @@ import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.Result
import code.name.monkey.retromusic.network.model.LastFmAlbum import code.name.monkey.retromusic.network.model.LastFmAlbum
import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.*
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.attached.AttachedCab import com.afollestad.materialcab.attached.AttachedCab
import com.afollestad.materialcab.attached.destroy import com.afollestad.materialcab.attached.destroy
import com.afollestad.materialcab.attached.isActive import com.afollestad.materialcab.attached.isActive
@ -245,10 +242,10 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
detailsViewModel.getAlbumInfo(album).observe(viewLifecycleOwner) { result -> detailsViewModel.getAlbumInfo(album).observe(viewLifecycleOwner) { result ->
when (result) { when (result) {
is Result.Loading -> { is Result.Loading -> {
println("Loading") logD("Loading")
} }
is Result.Error -> { is Result.Error -> {
println("Error") logE("Error")
} }
is Result.Success -> { is Result.Success -> {
aboutAlbum(result.data) aboutAlbum(result.data)

View file

@ -367,7 +367,6 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab { override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab {
cab?.let { cab?.let {
println("Cab")
if (it.isActive()) { if (it.isActive()) {
it.destroy() it.destroy()
} }

View file

@ -180,8 +180,8 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
detailsViewModel.getArtistInfo(name, lang, null) detailsViewModel.getArtistInfo(name, lang, null)
.observe(viewLifecycleOwner) { result -> .observe(viewLifecycleOwner) { result ->
when (result) { when (result) {
is Result.Loading -> println("Loading") is Result.Loading -> logD("Loading")
is Result.Error -> println("Error") is Result.Error -> logE("Error")
is Result.Success -> artistInfo(result.data) is Result.Success -> artistInfo(result.data)
} }
} }

View file

@ -22,7 +22,7 @@ import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.helper.BackupHelper import code.name.monkey.retromusic.helper.BackupHelper
import code.name.monkey.retromusic.helper.sanitize import code.name.monkey.retromusic.helper.sanitize
import code.name.monkey.retromusic.util.BackupUtil import code.name.monkey.retromusic.util.Share
import com.afollestad.materialdialogs.input.input import com.afollestad.materialdialogs.input.input
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -128,12 +128,7 @@ class BackupFragment : Fragment(R.layout.fragment_backup), BackupAdapter.BackupC
return true return true
} }
R.id.action_share -> { R.id.action_share -> {
activity?.startActivity( Share.shareFile(requireContext(), file, "*/*")
Intent.createChooser(
BackupUtil.createShareFileIntent(file, requireContext()),
null
)
)
return true return true
} }
R.id.action_rename -> { R.id.action_rename -> {

View file

@ -23,6 +23,7 @@ import androidx.navigation.navOptions
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
import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
import code.name.monkey.retromusic.util.maybeShowAnnoyingToasts
/** /**
* Created by hemanths on 18/08/17. * Created by hemanths on 18/08/17.
@ -63,6 +64,7 @@ open class AbsMusicServiceFragment(@LayoutRes layout: Int) : Fragment(layout),
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
serviceActivity?.addMusicServiceEventListener(this) serviceActivity?.addMusicServiceEventListener(this)
maybeShowAnnoyingToasts()
} }
override fun onDestroyView() { override fun onDestroyView() {

View file

@ -35,11 +35,11 @@ import code.name.monkey.retromusic.fragments.MusicSeekSkipTouchListener
import code.name.monkey.retromusic.fragments.other.VolumeFragment import code.name.monkey.retromusic.fragments.other.VolumeFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
/** /**
* Created by hemanths on 24/09/17. * Created by hemanths on 24/09/17.
@ -58,10 +58,11 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
var lastDisabledPlaybackControlsColor: Int = 0 var lastDisabledPlaybackControlsColor: Int = 0
var isSeeking = false private var isSeeking = false
private set
open val progressSlider: SeekBar? = null open val progressSlider: Slider? = null
open val seekBar: SeekBar? = null
abstract val shuffleButton: ImageButton abstract val shuffleButton: ImageButton
@ -78,46 +79,77 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
private var progressAnimator: ObjectAnimator? = null private var progressAnimator: ObjectAnimator? = null
override fun onUpdateProgressViews(progress: Int, total: Int) { override fun onUpdateProgressViews(progress: Int, total: Int) {
progressSlider?.max = total if (seekBar == null) {
progressSlider?.valueTo = total.toFloat()
if (progress > total) return
progressSlider?.value = progress.toFloat()
} else {
seekBar?.max = total
if (isSeeking) { if (isSeeking) {
progressSlider?.progress = progress seekBar?.progress = progress
} else { } else {
progressAnimator = ObjectAnimator.ofInt(progressSlider, "progress", progress).apply { progressAnimator =
ObjectAnimator.ofInt(seekBar, "progress", progress).apply {
duration = SLIDER_ANIMATION_TIME duration = SLIDER_ANIMATION_TIME
interpolator = LinearInterpolator() interpolator = LinearInterpolator()
start() start()
} }
} }
}
songTotalTime?.text = MusicUtil.getReadableDurationString(total.toLong()) songTotalTime?.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress?.text = MusicUtil.getReadableDurationString(progress.toLong()) songCurrentProgress?.text = MusicUtil.getReadableDurationString(progress.toLong())
} }
private fun setUpProgressSlider() { private fun setUpProgressSlider() {
progressSlider?.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() { progressSlider?.addOnChangeListener(Slider.OnChangeListener { _, value, fromUser ->
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { onProgressChange(value.toInt(), fromUser)
})
progressSlider?.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
onStartTrackingTouch()
}
override fun onStopTrackingTouch(slider: Slider) {
onStopTrackingTouch(slider.value.toInt())
}
})
seekBar?.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
onProgressChange(progress, fromUser)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
onStartTrackingTouch()
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
onStopTrackingTouch(seekBar?.progress ?: 0)
}
})
}
private fun onProgressChange(value: Int, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
onUpdateProgressViews( onUpdateProgressViews(value, MusicPlayerRemote.songDurationMillis)
progress,
MusicPlayerRemote.songDurationMillis
)
} }
} }
override fun onStartTrackingTouch(seekBar: SeekBar) { private fun onStartTrackingTouch() {
isSeeking = true isSeeking = true
progressViewUpdateHelper.stop() progressViewUpdateHelper.stop()
progressAnimator?.cancel() progressAnimator?.cancel()
} }
override fun onStopTrackingTouch(seekBar: SeekBar) { private fun onStopTrackingTouch(value: Int) {
isSeeking = false isSeeking = false
MusicPlayerRemote.seekTo(seekBar.progress) MusicPlayerRemote.seekTo(value)
progressViewUpdateHelper.start() progressViewUpdateHelper.start()
} }
})
}
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper

View file

@ -163,8 +163,10 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMusicServiceFragme
R.id.now_playing -> { R.id.now_playing -> {
requireActivity().findNavController(R.id.fragment_container).navigate( requireActivity().findNavController(R.id.fragment_container).navigate(
R.id.playing_queue_fragment, R.id.playing_queue_fragment,
null null,
navOptions { launchSingleTop = true }
) )
mainActivity.collapsePanel()
return true return true
} }
R.id.action_show_lyrics -> { R.id.action_show_lyrics -> {
@ -289,6 +291,15 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMusicServiceFragme
} }
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (PreferenceUtil.circlePlayButton) {
requireContext().theme.applyStyle(R.style.CircleFABOverlay, true)
} else {
requireContext().theme.applyStyle(R.style.RoundedFABOverlay, true)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
if (PreferenceUtil.isFullScreenMode && if (PreferenceUtil.isFullScreenMode &&
@ -316,7 +327,15 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMusicServiceFragme
showLyricsIcon(this) showLyricsIcon(this)
} }
} }
requireView().setOnTouchListener( }
override fun onStart() {
super.onStart()
addSwipeDetector()
}
fun addSwipeDetector() {
view?.setOnTouchListener(
if (PreferenceUtil.swipeAnywhereToChangeSong) { if (PreferenceUtil.swipeAnywhereToChangeSong) {
SwipeDetector( SwipeDetector(
requireContext(), requireContext(),
@ -421,8 +440,7 @@ fun goToLyrics(activity: Activity) {
findNavController(R.id.fragment_container).navigate( findNavController(R.id.fragment_container).navigate(
R.id.lyrics_fragment, R.id.lyrics_fragment,
null, null,
navOptions { launchSingleTop = true }, navOptions { launchSingleTop = true }
null
) )
} }
} }

View file

@ -19,6 +19,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager import androidx.transition.TransitionManager
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil
import code.name.monkey.retromusic.util.logD
import com.google.android.material.transition.MaterialFade import com.google.android.material.transition.MaterialFade
abstract class AbsRecyclerViewCustomGridSizeFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> : abstract class AbsRecyclerViewCustomGridSizeFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> :
@ -73,7 +74,7 @@ abstract class AbsRecyclerViewCustomGridSizeFragment<A : RecyclerView.Adapter<*>
fun setAndSaveSortOrder(sortOrder: String) { fun setAndSaveSortOrder(sortOrder: String) {
this.sortOrder = sortOrder this.sortOrder = sortOrder
println(sortOrder) logD(sortOrder)
saveSortOrder(sortOrder) saveSortOrder(sortOrder)
setSortOrder(sortOrder) setSortOrder(sortOrder)
} }

View file

@ -216,7 +216,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
override fun onMenuItemSelected(item: MenuItem): Boolean { override fun onMenuItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.action_settings -> findNavController().navigate( R.id.action_settings -> findNavController().navigate(
R.id.settingsActivity, R.id.settings_fragment,
null, null,
navOptions navOptions
) )

View file

@ -24,6 +24,7 @@ import android.view.View
import android.webkit.MimeTypeMap import android.webkit.MimeTypeMap
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.Toolbar
import androidx.core.text.parseAsHtml import androidx.core.text.parseAsHtml
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -66,7 +67,6 @@ import com.afollestad.materialcab.attached.AttachedCab
import com.afollestad.materialcab.attached.destroy import com.afollestad.materialcab.attached.destroy
import com.afollestad.materialcab.attached.isActive import com.afollestad.materialcab.attached.isActive
import com.afollestad.materialcab.createCab import com.afollestad.materialcab.createCab
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialFadeThrough import com.google.android.material.transition.MaterialFadeThrough
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -83,6 +83,9 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
LoaderManager.LoaderCallbacks<List<File>>, StorageClickListener { LoaderManager.LoaderCallbacks<List<File>>, StorageClickListener {
private var _binding: FragmentFolderBinding? = null private var _binding: FragmentFolderBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
val toolbar: Toolbar get() = binding.appBarLayout.toolbar
private var adapter: SongFileAdapter? = null private var adapter: SongFileAdapter? = null
private var storageAdapter: StorageAdapter? = null private var storageAdapter: StorageAdapter? = null
private var cab: AttachedCab? = null private var cab: AttachedCab? = null
@ -100,7 +103,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
_binding = FragmentFolderBinding.bind(view) _binding = FragmentFolderBinding.bind(view)
mainActivity.addMusicServiceEventListener(libraryViewModel) mainActivity.addMusicServiceEventListener(libraryViewModel)
mainActivity.setSupportActionBar(binding.toolbar) mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null mainActivity.supportActionBar?.title = null
enterTransition = MaterialFadeThrough() enterTransition = MaterialFadeThrough()
reenterTransition = MaterialFadeThrough() reenterTransition = MaterialFadeThrough()
@ -119,16 +122,13 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
} }
} }
}) })
binding.toolbarContainer.drawNextToNavbar()
binding.appBarLayout.statusBarForeground =
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
} }
private fun setUpTitle() { private fun setUpTitle() {
binding.toolbar.setNavigationOnClickListener { toolbar.setNavigationOnClickListener {
findNavController().navigate(R.id.action_search, null, navOptions) findNavController().navigate(R.id.action_search, null, navOptions)
} }
binding.appNameText.text = resources.getString(R.string.folders) binding.appBarLayout.title = resources.getString(R.string.folders)
} }
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
@ -185,7 +185,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
listSongs( listSongs(
requireContext(), requireContext(),
toList(file), listOf(file),
AUDIO_FILE_FILTER, AUDIO_FILE_FILTER,
fileComparator fileComparator
) { songs -> ) { songs ->
@ -226,7 +226,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
listSongs( listSongs(
requireContext(), requireContext(),
toList(file), listOf(file),
AUDIO_FILE_FILTER, AUDIO_FILE_FILTER,
fileComparator fileComparator
) { songs -> ) { songs ->
@ -264,7 +264,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
listSongs( listSongs(
requireContext(), requireContext(),
toList(mFile.parentFile), listOf(mFile.parentFile),
fileFilter, fileFilter,
fileComparator fileComparator
) { songs -> ) { songs ->
@ -332,7 +332,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
} }
override fun onPrepareMenu(menu: Menu) { override fun onPrepareMenu(menu: Menu) {
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(requireActivity(), binding.toolbar) ToolbarContentTintHelper.handleOnPrepareOptionsMenu(requireActivity(), toolbar)
} }
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
@ -346,8 +346,8 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
menu.removeItem(R.id.action_layout_type) menu.removeItem(R.id.action_layout_type)
menu.removeItem(R.id.action_sort_order) menu.removeItem(R.id.action_sort_order)
ToolbarContentTintHelper.handleOnCreateOptionsMenu( ToolbarContentTintHelper.handleOnCreateOptionsMenu(
requireContext(), binding.toolbar, menu, ATHToolbarActivity.getToolbarBackgroundColor( requireContext(), toolbar, menu, ATHToolbarActivity.getToolbarBackgroundColor(
binding.toolbar toolbar
) )
) )
} }
@ -374,7 +374,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
} }
R.id.action_settings -> { R.id.action_settings -> {
findNavController().navigate( findNavController().navigate(
R.id.settingsActivity, R.id.settings_fragment,
null, null,
navOptions navOptions
) )
@ -501,12 +501,6 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
) )
} }
private fun toList(file: File): ArrayList<File> {
val files = ArrayList<File>(1)
files.add(file)
return files
}
private fun updateAdapter(files: List<File>) { private fun updateAdapter(files: List<File>) {
adapter?.swapDataSet(files) adapter?.swapDataSet(files)
val crumb = activeCrumb val crumb = activeCrumb
@ -578,7 +572,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
suspend fun listSongs( suspend fun listSongs(
context: Context, context: Context,
files: List<File>, files: List<File?>,
fileFilter: FileFilter, fileFilter: FileFilter,
fileComparator: Comparator<File>, fileComparator: Comparator<File>,
doOnSongsListed: (songs: List<Song>) -> Unit doOnSongsListed: (songs: List<Song>) -> Unit

View file

@ -47,6 +47,7 @@ import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.IScrollHelper import code.name.monkey.retromusic.interfaces.IScrollHelper
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.PreferenceUtil.userName import code.name.monkey.retromusic.util.PreferenceUtil.userName
import com.google.android.gms.cast.framework.CastButtonFactory import com.google.android.gms.cast.framework.CastButtonFactory
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
@ -221,7 +222,7 @@ class HomeFragment :
} }
private fun loadSuggestions(songs: List<Song>) { private fun loadSuggestions(songs: List<Song>) {
if (songs.isEmpty()) { if (!PreferenceUtil.homeSuggestions || songs.isEmpty()) {
binding.suggestions.root.isVisible = false binding.suggestions.root.isVisible = false
return return
} }
@ -277,7 +278,7 @@ class HomeFragment :
override fun onMenuItemSelected(item: MenuItem): Boolean { override fun onMenuItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.action_settings -> findNavController().navigate( R.id.action_settings -> findNavController().navigate(
R.id.settingsActivity, R.id.settings_fragment,
null, null,
navOptions navOptions
) )

View file

@ -105,7 +105,7 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
override fun onMenuItemSelected(item: MenuItem): Boolean { override fun onMenuItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.action_settings -> findNavController().navigate( R.id.action_settings -> findNavController().navigate(
R.id.settingsActivity, R.id.settings_fragment,
null, null,
navOptions navOptions
) )

View file

@ -282,7 +282,6 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab { override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab {
cab?.let { cab?.let {
println("Cab")
if (it.isActive()) { if (it.isActive()) {
it.destroy() it.destroy()
} }

View file

@ -66,7 +66,10 @@ open class MiniPlayerFragment : AbsMusicServiceFragment(R.layout.fragment_mini_p
_binding = FragmentMiniPlayerBinding.bind(view) _binding = FragmentMiniPlayerBinding.bind(view)
view.setOnTouchListener(FlingPlayBackController(requireContext())) view.setOnTouchListener(FlingPlayBackController(requireContext()))
setUpMiniPlayer() setUpMiniPlayer()
setUpButtons()
}
fun setUpButtons() {
if (RetroUtil.isTablet) { if (RetroUtil.isTablet) {
binding.actionNext.show() binding.actionNext.show()
binding.actionPrevious.show() binding.actionPrevious.show()

View file

@ -21,7 +21,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.SeekBar
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
@ -32,8 +31,9 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.volume.AudioVolumeObserver import code.name.monkey.retromusic.volume.AudioVolumeObserver
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener
import com.google.android.material.slider.Slider
class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolumeChangedListener, class VolumeFragment : Fragment(), Slider.OnChangeListener, OnAudioVolumeChangedListener,
View.OnClickListener { View.OnClickListener {
private var _binding: FragmentVolumeBinding? = null private var _binding: FragmentVolumeBinding? = null
@ -47,7 +47,7 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
_binding = FragmentVolumeBinding.inflate(inflater, container, false) _binding = FragmentVolumeBinding.inflate(inflater, container, false)
return binding.root return binding.root
@ -68,15 +68,17 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
audioVolumeObserver?.register(AudioManager.STREAM_MUSIC, this) audioVolumeObserver?.register(AudioManager.STREAM_MUSIC, this)
val audioManager = audioManager val audioManager = audioManager
binding.volumeSeekBar.max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) binding.volumeSeekBar.valueTo =
binding.volumeSeekBar.progress = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
binding.volumeSeekBar.setOnSeekBarChangeListener(this) binding.volumeSeekBar.value =
audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat()
binding.volumeSeekBar.addOnChangeListener(this)
} }
override fun onAudioVolumeChanged(currentVolume: Int, maxVolume: Int) { override fun onAudioVolumeChanged(currentVolume: Int, maxVolume: Int) {
if (_binding != null) { if (_binding != null) {
binding.volumeSeekBar.max = maxVolume binding.volumeSeekBar.valueTo = maxVolume.toFloat()
binding.volumeSeekBar.progress = currentVolume binding.volumeSeekBar.value = currentVolume.toFloat()
binding.volumeDown.setImageResource(if (currentVolume == 0) R.drawable.ic_volume_off else R.drawable.ic_volume_down) binding.volumeDown.setImageResource(if (currentVolume == 0) R.drawable.ic_volume_off else R.drawable.ic_volume_down)
} }
} }
@ -87,17 +89,11 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
_binding = null _binding = null
} }
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) { override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
val audioManager = audioManager val audioManager = audioManager
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, i, 0) audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value.toInt(), 0)
setPauseWhenZeroVolume(i < 1) setPauseWhenZeroVolume(value < 1f)
binding.volumeDown.setImageResource(if (i == 0) R.drawable.ic_volume_off else R.drawable.ic_volume_down) binding.volumeDown.setImageResource(if (value == 0f) R.drawable.ic_volume_off else R.drawable.ic_volume_down)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
} }
override fun onClick(view: View) { override fun onClick(view: View) {

View file

@ -102,8 +102,6 @@ class CoverLyricsFragment : AbsMusicServiceFragment(R.layout.fragment_cover_lyri
null null
} }
} }
} }
override fun onUpdateProgressViews(progress: Int, total: Int) { override fun onUpdateProgressViews(progress: Int, total: Int) {

View file

@ -49,6 +49,7 @@ import code.name.monkey.retromusic.util.LyricUtil
import code.name.monkey.retromusic.util.LyricsType import code.name.monkey.retromusic.util.LyricsType
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import code.name.monkey.retromusic.util.logD
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -115,6 +116,22 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
_binding = FragmentPlayerAlbumCoverBinding.bind(view) _binding = FragmentPlayerAlbumCoverBinding.bind(view)
setupViewPager()
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
maybeInitLyrics()
lrcView.apply {
setDraggable(true) { time ->
MusicPlayerRemote.seekTo(time.toInt())
MusicPlayerRemote.resumePlaying()
true
}
setOnClickListener {
goToLyrics(requireActivity())
}
}
}
private fun setupViewPager() {
binding.viewPager.addOnPageChangeListener(this) binding.viewPager.addOnPageChangeListener(this)
val nps = PreferenceUtil.nowPlayingScreen val nps = PreferenceUtil.nowPlayingScreen
@ -140,18 +157,6 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
PreferenceUtil.albumCoverTransform PreferenceUtil.albumCoverTransform
) )
} }
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
maybeInitLyrics()
lrcView.apply {
setDraggable(true) { time ->
MusicPlayerRemote.seekTo(time.toInt())
MusicPlayerRemote.resumePlaying()
true
}
setOnClickListener {
goToLyrics(requireActivity())
}
}
} }
override fun onResume() { override fun onResume() {
@ -171,31 +176,37 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
} }
override fun onServiceConnected() { override fun onServiceConnected() {
logD("Service Connected")
updatePlayingQueue() updatePlayingQueue()
updateLyrics() updateLyrics()
} }
override fun onPlayingMetaChanged() { override fun onPlayingMetaChanged() {
binding.viewPager.currentItem = MusicPlayerRemote.position logD("Playing Meta Changed")
viewPager.setCurrentItem(MusicPlayerRemote.position, true)
updateLyrics() updateLyrics()
} }
override fun onQueueChanged() { override fun onQueueChanged() {
logD("Queue Changed")
updatePlayingQueue() updatePlayingQueue()
} }
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
if (key == SHOW_LYRICS) { when (key) {
if (sharedPreferences.getBoolean(key, false)) { SHOW_LYRICS -> {
if (PreferenceUtil.showLyrics) {
maybeInitLyrics() maybeInitLyrics()
} else { } else {
showLyrics(false) showLyrics(false)
progressViewUpdateHelper?.stop() progressViewUpdateHelper?.stop()
} }
} else if (key == LYRICS_TYPE) { }
LYRICS_TYPE -> {
maybeInitLyrics() maybeInitLyrics()
} }
} }
}
private fun setLRCViewColors(@ColorInt primaryColor: Int, @ColorInt secondaryColor: Int) { private fun setLRCViewColors(@ColorInt primaryColor: Int, @ColorInt secondaryColor: Int) {
lrcView.apply { lrcView.apply {
@ -244,7 +255,7 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
binding.viewPager.apply { binding.viewPager.apply {
adapter = AlbumCoverPagerAdapter(childFragmentManager, MusicPlayerRemote.playingQueue) adapter = AlbumCoverPagerAdapter(childFragmentManager, MusicPlayerRemote.playingQueue)
adapter?.notifyDataSetChanged() adapter?.notifyDataSetChanged()
currentItem = MusicPlayerRemote.position setCurrentItem(MusicPlayerRemote.position, true)
onPageSelected(MusicPlayerRemote.position) onPageSelected(MusicPlayerRemote.position)
} }
} }

View file

@ -17,9 +17,7 @@ package code.name.monkey.retromusic.fragments.player.adaptive
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
@ -31,6 +29,7 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
class AdaptivePlaybackControlsFragment : class AdaptivePlaybackControlsFragment :
AbsPlayerControlsFragment(R.layout.fragment_adaptive_player_playback_controls) { AbsPlayerControlsFragment(R.layout.fragment_adaptive_player_playback_controls) {
@ -38,7 +37,7 @@ class AdaptivePlaybackControlsFragment :
private var _binding: FragmentAdaptivePlayerPlaybackControlsBinding? = null private var _binding: FragmentAdaptivePlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -124,7 +123,7 @@ class AdaptivePlaybackControlsFragment :
val colorFinal = if (PreferenceUtil.isAdaptiveColor) { val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()) accentColor()
}.ripAlpha() }.ripAlpha()
TintHelper.setTintAuto( TintHelper.setTintAuto(

View file

@ -19,7 +19,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
@ -37,13 +36,14 @@ import code.name.monkey.retromusic.fragments.base.goToArtist
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
class BlurPlaybackControlsFragment : class BlurPlaybackControlsFragment :
AbsPlayerControlsFragment(R.layout.fragment_blur_player_playback_controls) { AbsPlayerControlsFragment(R.layout.fragment_blur_player_playback_controls) {
private var _binding: FragmentBlurPlayerPlaybackControlsBinding? = null private var _binding: FragmentBlurPlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton

View file

@ -20,17 +20,13 @@ import android.view.View
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.databinding.FragmentCardPlayerPlaybackControlsBinding import code.name.monkey.retromusic.databinding.FragmentCardPlayerPlaybackControlsBinding
import code.name.monkey.retromusic.extensions.getSongInfo import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.ripAlpha
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.fragments.base.goToAlbum import code.name.monkey.retromusic.fragments.base.goToAlbum
import code.name.monkey.retromusic.fragments.base.goToArtist import code.name.monkey.retromusic.fragments.base.goToArtist
@ -45,7 +41,7 @@ class CardPlaybackControlsFragment :
private var _binding: FragmentCardPlayerPlaybackControlsBinding? = null private var _binding: FragmentCardPlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val seekBar: SeekBar
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -138,7 +134,7 @@ class CardPlaybackControlsFragment :
val colorFinal = if (PreferenceUtil.isAdaptiveColor) { val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()).ripAlpha() accentColor().ripAlpha()
} }
binding.image.setColorFilter(colorFinal, PorterDuff.Mode.SRC_IN) binding.image.setColorFilter(colorFinal, PorterDuff.Mode.SRC_IN)
TintHelper.setTintAuto( TintHelper.setTintAuto(

View file

@ -19,7 +19,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
@ -34,6 +33,7 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
class CardBlurPlaybackControlsFragment : class CardBlurPlaybackControlsFragment :
AbsPlayerControlsFragment(R.layout.fragment_card_blur_player_playback_controls) { AbsPlayerControlsFragment(R.layout.fragment_card_blur_player_playback_controls) {
@ -41,7 +41,7 @@ class CardBlurPlaybackControlsFragment :
private var _binding: FragmentCardBlurPlayerPlaybackControlsBinding? = null private var _binding: FragmentCardBlurPlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton

View file

@ -25,10 +25,8 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.Animation import android.view.animation.Animation
import android.view.animation.LinearInterpolator import android.view.animation.LinearInterpolator
import android.widget.SeekBar
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
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.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
@ -49,13 +47,12 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import code.name.monkey.retromusic.volume.AudioVolumeObserver import code.name.monkey.retromusic.volume.AudioVolumeObserver
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener
import com.google.android.material.slider.Slider
import me.tankery.lib.circularseekbar.CircularSeekBar import me.tankery.lib.circularseekbar.CircularSeekBar
/** /**
@ -78,6 +75,9 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
private var rotateAnimator: ObjectAnimator? = null private var rotateAnimator: ObjectAnimator? = null
private var lastRequest: GlideRequest<Drawable>? = null private var lastRequest: GlideRequest<Drawable>? = null
private var progressAnimator: ObjectAnimator? = null
var isSeeking = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this) progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
@ -113,11 +113,6 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
private fun setupViews() { private fun setupViews() {
setUpProgressSlider() setUpProgressSlider()
ViewUtil.setProgressDrawable(
binding.progressSlider,
ThemeStore.accentColor(requireContext()),
false
)
binding.volumeSeekBar.circleProgressColor = accentColor() binding.volumeSeekBar.circleProgressColor = accentColor()
binding.volumeSeekBar.circleColor = ColorUtil.withAlpha(accentColor(), 0.25f) binding.volumeSeekBar.circleColor = ColorUtil.withAlpha(accentColor(), 0.25f)
setUpPlayPauseFab() setUpPlayPauseFab()
@ -135,11 +130,12 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
private fun setUpPrevNext() { private fun setUpPrevNext() {
updatePrevNextColor() updatePrevNextColor()
binding.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true)) binding.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true))
binding.previousButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), false)) binding.previousButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(),
false))
} }
private fun updatePrevNextColor() { private fun updatePrevNextColor() {
val accentColor = ThemeStore.accentColor(requireContext()) val accentColor = accentColor()
binding.nextButton.setColorFilter(accentColor, PorterDuff.Mode.SRC_IN) binding.nextButton.setColorFilter(accentColor, PorterDuff.Mode.SRC_IN)
binding.previousButton.setColorFilter(accentColor, PorterDuff.Mode.SRC_IN) binding.previousButton.setColorFilter(accentColor, PorterDuff.Mode.SRC_IN)
} }
@ -147,7 +143,7 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
private fun setUpPlayPauseFab() { private fun setUpPlayPauseFab() {
TintHelper.setTintAuto( TintHelper.setTintAuto(
binding.playPauseButton, binding.playPauseButton,
ThemeStore.accentColor(requireContext()), accentColor(),
false false
) )
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler()) binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
@ -275,7 +271,11 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
} }
override fun onProgressChanged(seekBar: CircularSeekBar?, progress: Float, fromUser: Boolean) { override fun onProgressChanged(
circularSeekBar: CircularSeekBar?,
progress: Float,
fromUser: Boolean,
) {
val audioManager = audioManager val audioManager = audioManager
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress.toInt(), 0) audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress.toInt(), 0)
} }
@ -286,28 +286,45 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
override fun onStopTrackingTouch(seekBar: CircularSeekBar?) { override fun onStopTrackingTouch(seekBar: CircularSeekBar?) {
} }
fun setUpProgressSlider() { private fun setUpProgressSlider() {
binding.progressSlider.applyColor(accentColor()) binding.progressSlider.applyColor(accentColor())
binding.progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() { val progressSlider = binding.progressSlider
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { progressSlider.addOnChangeListener(Slider.OnChangeListener { _, value, fromUser ->
if (fromUser) { if (fromUser) {
MusicPlayerRemote.seekTo(progress)
onUpdateProgressViews( onUpdateProgressViews(
MusicPlayerRemote.songProgressMillis, value.toInt(),
MusicPlayerRemote.songDurationMillis MusicPlayerRemote.songDurationMillis
) )
} }
})
progressSlider.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
isSeeking = true
progressViewUpdateHelper.stop()
}
override fun onStopTrackingTouch(slider: Slider) {
isSeeking = false
MusicPlayerRemote.seekTo(slider.value.toInt())
progressViewUpdateHelper.start()
} }
}) })
} }
override fun onUpdateProgressViews(progress: Int, total: Int) { override fun onUpdateProgressViews(progress: Int, total: Int) {
binding.progressSlider.max = total val progressSlider = binding.progressSlider
progressSlider.valueTo = total.toFloat()
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress) if (isSeeking) {
animator.duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME progressSlider.value = progress.toFloat()
animator.interpolator = LinearInterpolator() } else {
animator.start() progressAnimator =
ObjectAnimator.ofFloat(progressSlider, "value", progress.toFloat()).apply {
duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME
interpolator = LinearInterpolator()
start()
}
}
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong()) binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong()) binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())

View file

@ -22,7 +22,6 @@ import android.view.ViewAnimationUtils
import android.view.animation.AccelerateInterpolator import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
@ -38,6 +37,7 @@ import code.name.monkey.retromusic.fragments.base.goToArtist
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
import kotlin.math.sqrt import kotlin.math.sqrt
class ColorPlaybackControlsFragment : class ColorPlaybackControlsFragment :
@ -46,7 +46,7 @@ class ColorPlaybackControlsFragment :
private var _binding: FragmentColorPlayerPlaybackControlsBinding? = null private var _binding: FragmentColorPlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton

View file

@ -20,7 +20,6 @@ import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
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.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
@ -40,7 +39,7 @@ class FitPlaybackControlsFragment :
private var _binding: FragmentFitPlaybackControlsBinding? = null private var _binding: FragmentFitPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val seekBar: SeekBar
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -128,7 +127,7 @@ class FitPlaybackControlsFragment :
val colorFinal = if (PreferenceUtil.isAdaptiveColor) { val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()).ripAlpha() accentColor().ripAlpha()
} }
volumeFragment?.setTintable(colorFinal) volumeFragment?.setTintable(colorFinal)

View file

@ -20,7 +20,6 @@ import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
@ -43,7 +42,7 @@ class FlatPlaybackControlsFragment :
private var _binding: FragmentFlatPlayerPlaybackControlsBinding? = null private var _binding: FragmentFlatPlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val seekBar: SeekBar
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -110,7 +109,7 @@ class FlatPlaybackControlsFragment :
val colorFinal = if (PreferenceUtil.isAdaptiveColor) { val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()).ripAlpha() accentColor().ripAlpha()
} }
updateTextColors(colorFinal) updateTextColors(colorFinal)

View file

@ -23,7 +23,6 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -45,6 +44,7 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -62,7 +62,7 @@ class FullPlaybackControlsFragment :
private var _binding: FragmentFullPlayerControlsBinding? = null private var _binding: FragmentFullPlayerControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -177,11 +177,10 @@ class FullPlaybackControlsFragment :
private fun setUpPlayPauseFab() { private fun setUpPlayPauseFab() {
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler()) binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
binding.playPauseButton.post {
binding.playPauseButton.pivotX = (binding.playPauseButton.width / 2).toFloat() binding.playPauseButton.pivotX = (binding.playPauseButton.width / 2).toFloat()
binding.playPauseButton.pivotY = (binding.playPauseButton.height / 2).toFloat() binding.playPauseButton.pivotY = (binding.playPauseButton.height / 2).toFloat()
} }
}
private fun setUpMusicControllers() { private fun setUpMusicControllers() {
setUpPlayPauseFab() setUpPlayPauseFab()

View file

@ -23,7 +23,6 @@ import android.graphics.drawable.AnimatedVectorDrawable
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.LinearInterpolator import android.view.animation.LinearInterpolator
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
@ -50,13 +49,13 @@ import code.name.monkey.retromusic.fragments.other.VolumeFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.* import com.google.android.material.bottomsheet.BottomSheetBehavior.*
import com.google.android.material.slider.Slider
import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager
@ -85,6 +84,9 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
private var _binding: FragmentGradientPlayerBinding? = null private var _binding: FragmentGradientPlayerBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private var progressAnimator: ObjectAnimator? = null
var isSeeking = false
private val bottomSheetCallbackList = object : BottomSheetCallback() { private val bottomSheetCallbackList = object : BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) { override fun onSlide(bottomSheet: View, slideOffset: Float) {
mainActivity.getBottomSheetBehavior().isDraggable = false mainActivity.getBottomSheetBehavior().isDraggable = false
@ -99,7 +101,8 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
override fun onStateChanged(bottomSheet: View, newState: Int) { override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) { when (newState) {
STATE_EXPANDED, STATE_EXPANDED,
STATE_DRAGGING -> { STATE_DRAGGING,
-> {
mainActivity.getBottomSheetBehavior().isDraggable = false mainActivity.getBottomSheetBehavior().isDraggable = false
} }
STATE_COLLAPSED -> { STATE_COLLAPSED -> {
@ -161,7 +164,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
ViewCompat.setOnApplyWindowInsetsListener( ViewCompat.setOnApplyWindowInsetsListener(
(binding.container) (binding.container)
) { v: View, insets: WindowInsetsCompat -> ) { v: View, insets: WindowInsetsCompat ->
navBarHeight = insets.safeGetBottomInsets() navBarHeight = insets.getBottomInsets()
v.updatePadding(bottom = navBarHeight) v.updatePadding(bottom = navBarHeight)
insets insets
} }
@ -312,7 +315,6 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
super.onServiceConnected() super.onServiceConnected()
updateSong() updateSong()
updatePlayPauseDrawableState() updatePlayPauseDrawableState()
updatePlayPauseDrawableState()
updateQueue() updateQueue()
updateIsFavoriteIcon() updateIsFavoriteIcon()
} }
@ -379,15 +381,17 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
private fun setUpPlayPauseFab() { private fun setUpPlayPauseFab() {
binding.playbackControlsFragment.playPauseButton.setOnClickListener( binding.playbackControlsFragment.playPauseButton.setOnClickListener(
PlayPauseButtonOnClickHandler() PlayPauseButtonOnClickHandler())
)
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
private fun setUpPrevNext() { private fun setUpPrevNext() {
updatePrevNextColor() updatePrevNextColor()
binding.playbackControlsFragment.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true)) binding.playbackControlsFragment.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(
binding.playbackControlsFragment.previousButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), false)) requireActivity(),
true))
binding.playbackControlsFragment.previousButton.setOnTouchListener(
MusicSeekSkipTouchListener(requireActivity(), false))
} }
private fun updatePrevNextColor() { private fun updatePrevNextColor() {
@ -469,7 +473,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
oldLeft: Int, oldLeft: Int,
oldTop: Int, oldTop: Int,
oldRight: Int, oldRight: Int,
oldBottom: Int oldBottom: Int,
) { ) {
val panel = getQueuePanel() val panel = getQueuePanel()
if (panel.state == STATE_COLLAPSED) { if (panel.state == STATE_COLLAPSED) {
@ -542,30 +546,43 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
} }
private fun setUpProgressSlider() { private fun setUpProgressSlider() {
binding.playbackControlsFragment.progressSlider.setOnSeekBarChangeListener(object : val progressSlider = binding.playbackControlsFragment.progressSlider
SimpleOnSeekbarChangeListener() { progressSlider.addOnChangeListener(Slider.OnChangeListener { _, value, fromUser ->
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
MusicPlayerRemote.seekTo(progress)
onUpdateProgressViews( onUpdateProgressViews(
MusicPlayerRemote.songProgressMillis, value.toInt(),
MusicPlayerRemote.songDurationMillis MusicPlayerRemote.songDurationMillis
) )
} }
})
progressSlider.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
isSeeking = true
progressViewUpdateHelper.stop()
}
override fun onStopTrackingTouch(slider: Slider) {
isSeeking = false
MusicPlayerRemote.seekTo(slider.value.toInt())
progressViewUpdateHelper.start()
} }
}) })
} }
override fun onUpdateProgressViews(progress: Int, total: Int) { override fun onUpdateProgressViews(progress: Int, total: Int) {
binding.playbackControlsFragment.progressSlider.max = total val progressSlider = binding.playbackControlsFragment.progressSlider
val animator = ObjectAnimator.ofInt( progressSlider.valueTo = total.toFloat()
binding.playbackControlsFragment.progressSlider,
"progress", if (isSeeking) {
progress progressSlider.value = progress.toFloat()
) } else {
animator.duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME progressAnimator =
animator.interpolator = LinearInterpolator() ObjectAnimator.ofFloat(progressSlider, "value", progress.toFloat()).apply {
animator.start() duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME
interpolator = LinearInterpolator()
start()
}
}
binding.playbackControlsFragment.songTotalTime.text = binding.playbackControlsFragment.songTotalTime.text =
MusicUtil.getReadableDurationString(total.toLong()) MusicUtil.getReadableDurationString(total.toLong())
binding.playbackControlsFragment.songCurrentProgress.text = binding.playbackControlsFragment.songCurrentProgress.text =

View file

@ -18,7 +18,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
@ -34,6 +33,7 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
/** /**
* @author Hemanth S (h4h13). * @author Hemanth S (h4h13).
@ -44,7 +44,7 @@ class LockScreenControlsFragment :
private var _binding: FragmentLockScreenPlaybackControlsBinding? = null private var _binding: FragmentLockScreenPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton

View file

@ -18,7 +18,6 @@ import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
@ -33,6 +32,7 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
/** /**
* @author Hemanth S (h4h13). * @author Hemanth S (h4h13).
@ -44,7 +44,7 @@ class MaterialControlsFragment :
private var _binding: FragmentMaterialPlaybackControlsBinding? = null private var _binding: FragmentMaterialPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton

View file

@ -14,12 +14,9 @@
*/ */
package code.name.monkey.retromusic.fragments.player.md3 package code.name.monkey.retromusic.fragments.player.md3
import android.animation.ObjectAnimator
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.LinearInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
@ -32,20 +29,18 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.fragments.base.goToAlbum import code.name.monkey.retromusic.fragments.base.goToAlbum
import code.name.monkey.retromusic.fragments.base.goToArtist import code.name.monkey.retromusic.fragments.base.goToArtist
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
class MD3PlaybackControlsFragment : class MD3PlaybackControlsFragment :
AbsPlayerControlsFragment(R.layout.fragment_md3_player_playback_controls) { AbsPlayerControlsFragment(R.layout.fragment_md3_player_playback_controls) {
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
private var _binding: FragmentMd3PlayerPlaybackControlsBinding? = null private var _binding: FragmentMd3PlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -66,11 +61,6 @@ class MD3PlaybackControlsFragment :
override val songCurrentProgress: TextView override val songCurrentProgress: TextView
get() = binding.songCurrentProgress get() = binding.songCurrentProgress
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
_binding = FragmentMd3PlayerPlaybackControlsBinding.bind(view) _binding = FragmentMd3PlayerPlaybackControlsBinding.bind(view)
@ -139,16 +129,6 @@ class MD3PlaybackControlsFragment :
} }
} }
override fun onResume() {
super.onResume()
progressViewUpdateHelper.start()
}
override fun onPause() {
super.onPause()
progressViewUpdateHelper.stop()
}
override fun onServiceConnected() { override fun onServiceConnected() {
updatePlayPauseDrawableState() updatePlayPauseDrawableState()
updateRepeatState() updateRepeatState()
@ -157,7 +137,6 @@ class MD3PlaybackControlsFragment :
} }
override fun onPlayingMetaChanged() { override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
updateSong() updateSong()
} }
@ -196,18 +175,6 @@ class MD3PlaybackControlsFragment :
public override fun hide() {} public override fun hide() {}
override fun onUpdateProgressViews(progress: Int, total: Int) {
binding.progressSlider.max = total
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
animator.duration = SLIDER_ANIMATION_TIME
animator.interpolator = LinearInterpolator()
animator.start()
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View file

@ -164,6 +164,7 @@ class PlayerFragment : AbsPlayerFragment(R.layout.fragment_player),
} }
private fun startOrStopSnow(isSnowFalling: Boolean) { private fun startOrStopSnow(isSnowFalling: Boolean) {
if (_binding == null) return
if (isSnowFalling && !surfaceColor().isColorLight) { if (isSnowFalling && !surfaceColor().isColorLight) {
binding.snowfallView.isVisible = true binding.snowfallView.isVisible = true
binding.snowfallView.restartFalling() binding.snowfallView.restartFalling()

View file

@ -18,9 +18,7 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
@ -34,6 +32,7 @@ import code.name.monkey.retromusic.fragments.base.goToArtist
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
class PlayerPlaybackControlsFragment : class PlayerPlaybackControlsFragment :
AbsPlayerControlsFragment(R.layout.fragment_player_playback_controls) { AbsPlayerControlsFragment(R.layout.fragment_player_playback_controls) {
@ -41,7 +40,7 @@ class PlayerPlaybackControlsFragment :
private var _binding: FragmentPlayerPlaybackControlsBinding? = null private var _binding: FragmentPlayerPlaybackControlsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -94,7 +93,7 @@ class PlayerPlaybackControlsFragment :
val colorFinal = if (PreferenceUtil.isAdaptiveColor) { val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()) accentColor()
}.ripAlpha() }.ripAlpha()
TintHelper.setTintAuto( TintHelper.setTintAuto(

View file

@ -19,20 +19,20 @@ import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.databinding.FragmentPeekControlPlayerBinding import code.name.monkey.retromusic.databinding.FragmentPeekControlPlayerBinding
import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.applyColor import code.name.monkey.retromusic.extensions.applyColor
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
/** /**
* Created by hemanths on 2019-10-04. * Created by hemanths on 2019-10-04.
@ -43,7 +43,7 @@ class PeekPlayerControlFragment : AbsPlayerControlsFragment(R.layout.fragment_pe
private var _binding: FragmentPeekControlPlayerBinding? = null private var _binding: FragmentPeekControlPlayerBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -82,7 +82,7 @@ class PeekPlayerControlFragment : AbsPlayerControlsFragment(R.layout.fragment_pe
if (PreferenceUtil.isAdaptiveColor) { if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()) accentColor()
} }
binding.progressSlider.applyColor(controlsColor) binding.progressSlider.applyColor(controlsColor)
volumeFragment?.setTintableColor(controlsColor) volumeFragment?.setTintableColor(controlsColor)

View file

@ -18,23 +18,19 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.databinding.FragmentPlainControlsFragmentBinding import code.name.monkey.retromusic.databinding.FragmentPlainControlsFragmentBinding
import code.name.monkey.retromusic.extensions.applyColor import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.extensions.getSongInfo
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.slider.Slider
/** /**
* @author Hemanth S (h4h13). * @author Hemanth S (h4h13).
@ -46,7 +42,7 @@ class PlainPlaybackControlsFragment :
private var _binding: FragmentPlainControlsFragmentBinding? = null private var _binding: FragmentPlainControlsFragmentBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
override val progressSlider: SeekBar override val progressSlider: Slider
get() = binding.progressSlider get() = binding.progressSlider
override val shuffleButton: ImageButton override val shuffleButton: ImageButton
@ -134,7 +130,7 @@ class PlainPlaybackControlsFragment :
val colorFinal = if (PreferenceUtil.isAdaptiveColor) { val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()) accentColor()
} }
volumeFragment?.setTintable(colorFinal) volumeFragment?.setTintable(colorFinal)
binding.progressSlider.applyColor(colorFinal) binding.progressSlider.applyColor(colorFinal)

View file

@ -18,13 +18,13 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.databinding.FragmentSimpleControlsFragmentBinding import code.name.monkey.retromusic.databinding.FragmentSimpleControlsFragmentBinding
import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.getSongInfo import code.name.monkey.retromusic.extensions.getSongInfo
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
@ -154,7 +154,7 @@ class SimplePlaybackControlsFragment :
val colorFinal = if (PreferenceUtil.isAdaptiveColor) { val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
color.primaryTextColor color.primaryTextColor
} else { } else {
ThemeStore.accentColor(requireContext()) accentColor()
} }
volumeFragment?.setTintable(colorFinal) volumeFragment?.setTintable(colorFinal)

View file

@ -177,7 +177,6 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab { override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab {
cab?.let { cab?.let {
println("Cab")
if (it.isActive()) { if (it.isActive()) {
it.destroy() it.destroy()
} }

View file

@ -50,6 +50,9 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
private var playingQueueAdapter: PlayingQueueAdapter? = null private var playingQueueAdapter: PlayingQueueAdapter? = null
private lateinit var linearLayoutManager: LinearLayoutManager private lateinit var linearLayoutManager: LinearLayoutManager
val mainActivity: MainActivity
get() = activity as MainActivity
private fun getUpNextAndQueueTime(): String { private fun getUpNextAndQueueTime(): String {
val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position) val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position)
return MusicUtil.buildInfoString( return MusicUtil.buildInfoString(
@ -69,6 +72,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
MusicPlayerRemote.clearQueue() MusicPlayerRemote.clearQueue()
} }
checkForPadding() checkForPadding()
mainActivity.collapsePanel()
} }
private fun setUpRecyclerView() { private fun setUpRecyclerView() {
@ -175,7 +179,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
playingQueueAdapter = null playingQueueAdapter = null
super.onDestroy() super.onDestroy()
if (MusicPlayerRemote.playingQueue.isNotEmpty()) if (MusicPlayerRemote.playingQueue.isNotEmpty())
(requireActivity() as MainActivity).expandPanel() mainActivity.expandPanel()
} }
private fun setupToolbar() { private fun setupToolbar() {

View file

@ -29,17 +29,12 @@ import androidx.core.widget.doAfterTextChanged
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager import androidx.transition.TransitionManager
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.SearchAdapter import code.name.monkey.retromusic.adapter.SearchAdapter
import code.name.monkey.retromusic.databinding.FragmentSearchBinding import code.name.monkey.retromusic.databinding.FragmentSearchBinding
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.extensions.focusAndShowKeyboard
import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.views.addAlpha
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
@ -133,7 +128,7 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search),
val colors = intArrayOf( val colors = intArrayOf(
android.R.color.transparent, android.R.color.transparent,
ThemeStore.accentColor(requireContext()).addAlpha(0.5F) accentColor().addAlpha(0.5F)
) )
chips.forEach { chips.forEach {

View file

@ -25,7 +25,6 @@ import androidx.preference.PreferenceManager
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.OnThemeChangedListener
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.preferences.* import code.name.monkey.retromusic.preferences.*
import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.NavigationUtil

View file

@ -25,6 +25,7 @@ import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.BLUETOOTH_PLAYBACK import code.name.monkey.retromusic.BLUETOOTH_PLAYBACK
import code.name.monkey.retromusic.EQUALIZER import code.name.monkey.retromusic.EQUALIZER
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsBaseActivity.Companion.BLUETOOTH_PERMISSION_REQUEST
import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.NavigationUtil
/** /**
@ -52,7 +53,7 @@ class AudioSettings : AbsSettingsFragment() {
BLUETOOTH_CONNECT) != PERMISSION_GRANTED BLUETOOTH_CONNECT) != PERMISSION_GRANTED
) { ) {
ActivityCompat.requestPermissions(requireActivity(), arrayOf( ActivityCompat.requestPermissions(requireActivity(), arrayOf(
BLUETOOTH_CONNECT), 100) BLUETOOTH_CONNECT), BLUETOOTH_PERMISSION_REQUEST)
} }
} }
return@setOnPreferenceChangeListener true return@setOnPreferenceChangeListener true

View file

@ -38,7 +38,6 @@ class OtherSettingsFragment : AbsSettingsFragment() {
override fun invalidateSettings() { override fun invalidateSettings() {
val languagePreference: ATEListPreference? = findPreference(LANGUAGE_NAME) val languagePreference: ATEListPreference? = findPreference(LANGUAGE_NAME)
languagePreference?.setOnPreferenceChangeListener { _, _ -> languagePreference?.setOnPreferenceChangeListener { _, _ ->
println("Invalidated")
restartActivity() restartActivity()
return@setOnPreferenceChangeListener true return@setOnPreferenceChangeListener true
} }

View file

@ -16,24 +16,20 @@ package code.name.monkey.retromusic.fragments.settings
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.preference.TwoStatePreference
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.HOME_ALBUM_GRID_STYLE
import code.name.monkey.retromusic.HOME_ARTIST_GRID_STYLE
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.TAB_TEXT_MODE
class PersonalizeSettingsFragment : AbsSettingsFragment() { class PersonalizeSettingsFragment : AbsSettingsFragment() {
override fun invalidateSettings() {
val toggleFullScreen: TwoStatePreference? = findPreference(TOGGLE_FULL_SCREEN)
toggleFullScreen?.setOnPreferenceChangeListener { _, _ ->
restartActivity()
true
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_ui) addPreferencesFromResource(R.xml.pref_ui)
} }
override fun invalidateSettings() {}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val homeArtistStyle: ATEListPreference? = findPreference(HOME_ARTIST_GRID_STYLE) val homeArtistStyle: ATEListPreference? = findPreference(HOME_ARTIST_GRID_STYLE)

View file

@ -12,42 +12,47 @@
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
*/ */
package code.name.monkey.retromusic.activities package code.name.monkey.retromusic.fragments.settings
import android.Manifest.permission.BLUETOOTH_CONNECT
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem import android.view.View
import androidx.core.view.updatePadding
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
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.appshortcuts.DynamicShortcutManager import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.databinding.ActivitySettingsBinding import code.name.monkey.retromusic.databinding.FragmentSettingsBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.applyToolbar
import code.name.monkey.retromusic.extensions.dip
import code.name.monkey.retromusic.extensions.extra
import code.name.monkey.retromusic.extensions.findNavController
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.color.ColorCallback import com.afollestad.materialdialogs.color.ColorCallback
class SettingsActivity : AbsBaseActivity(), ColorCallback, OnThemeChangedListener { class SettingsFragment : AbsMusicServiceFragment(R.layout.fragment_settings), ColorCallback {
private lateinit var binding: ActivitySettingsBinding private var _binding: FragmentSettingsBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
val mSavedInstanceState = extra<Bundle>(TAG).value ?: savedInstanceState val mSavedInstanceState = extra<Bundle>(TAG).value ?: savedInstanceState
super.onCreate(mSavedInstanceState) super.onCreate(mSavedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
setupToolbar()
setPermissionDeniedMessage(getString(R.string.permission_bluetooth_denied))
} }
override fun onResume() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onResume() _binding = FragmentSettingsBinding.bind(view)
setNavigationBarColorPreOreo(surfaceColor()) setupToolbar()
updateBottomPadding()
} }
private fun setupToolbar() { private fun setupToolbar() {
applyToolbar(binding.toolbar) applyToolbar(binding.toolbar)
binding.toolbar.setNavigationOnClickListener {
requireActivity().onBackPressed()
}
val navController: NavController = findNavController(R.id.contentFrame) val navController: NavController = findNavController(R.id.contentFrame)
navController.addOnDestinationChangedListener { _, _, _ -> navController.addOnDestinationChangedListener { _, _, _ ->
binding.collapsingToolbarLayout.title = binding.collapsingToolbarLayout.title =
@ -72,48 +77,32 @@ class SettingsActivity : AbsBaseActivity(), ColorCallback, OnThemeChangedListene
return getString(idRes) return getString(idRes)
} }
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.contentFrame).navigateUp() || super.onSupportNavigateUp()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
onBackPressed()
}
return super.onOptionsItemSelected(item)
}
override fun getPermissionsToRequest(): Array<String> {
return if (VersionUtils.hasS()) {
arrayOf(BLUETOOTH_CONNECT)
} else {
arrayOf()
}
}
override fun invoke(dialog: MaterialDialog, color: Int) { override fun invoke(dialog: MaterialDialog, color: Int) {
ThemeStore.editTheme(this).accentColor(color).commit() ThemeStore.editTheme(requireContext()).accentColor(color).commit()
if (VersionUtils.hasNougatMR()) if (VersionUtils.hasNougatMR())
DynamicShortcutManager(this).updateDynamicShortcuts() DynamicShortcutManager(requireContext()).updateDynamicShortcuts()
restart() restartActivity()
} }
override fun onThemeValuesChanged() { fun restartActivity() {
restart() if (activity is OnThemeChangedListener && !VersionUtils.hasS()) {
(activity as OnThemeChangedListener).onThemeValuesChanged()
} else {
activity?.recreate()
}
} }
private fun restart() { override fun onQueueChanged() {
val savedInstanceState = Bundle().apply { updateBottomPadding()
onSaveInstanceState(this)
} }
finish()
val intent = Intent(this, this::class.java).putExtra(TAG, savedInstanceState) private fun updateBottomPadding() {
startActivity(intent) binding.root.updatePadding(
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) bottom = if (MusicPlayerRemote.playingQueue.isEmpty()) 0 else dip(R.dimen.mini_player_height))
} }
companion object { companion object {
val TAG: String = SettingsActivity::class.java.simpleName val TAG: String = SettingsFragment::class.java.simpleName
} }
} }

View file

@ -29,6 +29,7 @@ import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.extensions.materialDialog import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import com.afollestad.materialdialogs.color.colorChooser import com.afollestad.materialdialogs.color.colorChooser
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
@ -130,6 +131,10 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
restartActivity() restartActivity()
true true
} }
val adaptiveColor: ATESwitchPreference? = findPreference(ADAPTIVE_COLOR_APP)
adaptiveColor?.isEnabled =
PreferenceUtil.nowPlayingScreen in listOf(Normal, Material, Flat)
} }
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {

View file

@ -363,7 +363,6 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab { override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab {
cab?.let { cab?.let {
println("Cab")
if (it.isActive()) { if (it.isActive()) {
it.destroy() it.destroy()
} }

View file

@ -15,26 +15,18 @@ import java.security.MessageDigest
@Suppress("Deprecation") @Suppress("Deprecation")
class BlurTransformation : BitmapTransformation { class BlurTransformation private constructor(builder: Builder) : BitmapTransformation() {
private var context: Context? = null private var context: Context? = null
private var blurRadius = 0f private var blurRadius = 0f
private var sampling = 0 private var sampling = 0
private fun init(builder: Builder) { init {
this.context = builder.context this.context = builder.context
this.blurRadius = builder.blurRadius this.blurRadius = builder.blurRadius
this.sampling = builder.sampling this.sampling = builder.sampling
} }
private constructor(builder: Builder) : super() {
init(builder)
}
private constructor(builder: Builder, bitmapPool: BitmapPool) : super() {
init(builder)
}
class Builder(val context: Context) { class Builder(val context: Context) {
private var bitmapPool: BitmapPool? = null private var bitmapPool: BitmapPool? = null
var blurRadius = DEFAULT_BLUR_RADIUS var blurRadius = DEFAULT_BLUR_RADIUS
@ -69,7 +61,7 @@ class BlurTransformation : BitmapTransformation {
fun build(): BlurTransformation { fun build(): BlurTransformation {
return if (bitmapPool != null) { return if (bitmapPool != null) {
BlurTransformation(this, bitmapPool!!) BlurTransformation(this)
} else BlurTransformation(this) } else BlurTransformation(this)
} }
} }
@ -78,7 +70,7 @@ class BlurTransformation : BitmapTransformation {
pool: BitmapPool, pool: BitmapPool,
toTransform: Bitmap, toTransform: Bitmap,
outWidth: Int, outWidth: Int,
outHeight: Int outHeight: Int,
): Bitmap { ): Bitmap {
val sampling = if (this.sampling == 0) { val sampling = if (this.sampling == 0) {
ImageUtil.calculateInSampleSize(toTransform.width, toTransform.height, 100) ImageUtil.calculateInSampleSize(toTransform.width, toTransform.height, 100)

View file

@ -55,17 +55,7 @@ class Factory(
val context: Context val context: Context
) : ModelLoaderFactory<ArtistImage, InputStream> { ) : ModelLoaderFactory<ArtistImage, InputStream> {
private var deezerService: DeezerService private var deezerService = DeezerService.invoke(
private var okHttp: OkHttpClient
init {
okHttp =
OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.build()
deezerService = DeezerService.invoke(
DeezerService.createDefaultOkHttpClient(context) DeezerService.createDefaultOkHttpClient(context)
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
@ -73,7 +63,12 @@ class Factory(
.addInterceptor(createLogInterceptor()) .addInterceptor(createLogInterceptor())
.build() .build()
) )
}
private var okHttp = OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.build()
private fun createLogInterceptor(): Interceptor { private fun createLogInterceptor(): Interceptor {
val interceptor = HttpLoggingInterceptor() val interceptor = HttpLoggingInterceptor()

View file

@ -28,12 +28,14 @@ import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.SongRepository import code.name.monkey.retromusic.repository.SongRepository
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.getExternalStorageDirectory import code.name.monkey.retromusic.util.getExternalStorageDirectory
import code.name.monkey.retromusic.util.logE
import com.google.android.gms.cast.framework.CastSession
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
import java.io.File import java.io.File
import java.util.* import java.util.*
import kotlin.collections.set
object MusicPlayerRemote : KoinComponent { object MusicPlayerRemote : KoinComponent {
@ -43,14 +45,6 @@ object MusicPlayerRemote : KoinComponent {
private val songRepository by inject<SongRepository>() private val songRepository by inject<SongRepository>()
var isCasting: Boolean = false
set(value) {
field = value
if (value) {
musicService?.quit()
}
}
@JvmStatic @JvmStatic
val isPlaying: Boolean val isPlaying: Boolean
get() = musicService != null && musicService!!.isPlaying get() = musicService != null && musicService!!.isPlaying
@ -71,9 +65,6 @@ object MusicPlayerRemote : KoinComponent {
musicService?.nextSong musicService?.nextSong
} else Song.emptySong } else Song.emptySong
/**
* Async
*/
var position: Int var position: Int
get() = if (musicService != null) { get() = if (musicService != null) {
musicService!!.position musicService!!.position
@ -121,11 +112,7 @@ object MusicPlayerRemote : KoinComponent {
fun bindToService(context: Context, callback: ServiceConnection): ServiceToken? { fun bindToService(context: Context, callback: ServiceConnection): ServiceToken? {
var realActivity: Activity? = (context as Activity).parent val realActivity = (context as Activity).parent ?: context
if (realActivity == null) {
realActivity = context
}
val contextWrapper = ContextWrapper(realActivity) val contextWrapper = ContextWrapper(realActivity)
val intent = Intent(contextWrapper, MusicService::class.java) val intent = Intent(contextWrapper, MusicService::class.java)
try { try {
@ -232,14 +219,9 @@ object MusicPlayerRemote : KoinComponent {
) && musicService != null ) && musicService != null
) { ) {
musicService?.openQueue(queue, startPosition, startPlaying) musicService?.openQueue(queue, startPosition, startPlaying)
if (PreferenceUtil.isShuffleModeOn)
setShuffleMode(MusicService.SHUFFLE_MODE_NONE)
} }
} }
/**
* Async
*/
@JvmStatic @JvmStatic
fun openAndShuffleQueue(queue: List<Song>, startPlaying: Boolean) { fun openAndShuffleQueue(queue: List<Song>, startPlaying: Boolean) {
var startPosition = 0 var startPosition = 0
@ -440,10 +422,10 @@ object MusicPlayerRemote : KoinComponent {
if (songs == null || songs.isEmpty()) { if (songs == null || songs.isEmpty()) {
var songFile: File? = null var songFile: File? = null
if (uri.authority != null && uri.authority == "com.android.externalstorage.documents") { if (uri.authority != null && uri.authority == "com.android.externalstorage.documents") {
songFile = File( val path = uri.path?.split(":".toRegex(), 2)?.get(1)
getExternalStorageDirectory(), if (path != null) {
uri.path?.split(":".toRegex(), 2)?.get(1) songFile = File(getExternalStorageDirectory(), path)
) }
} }
if (songFile == null) { if (songFile == null) {
val path = getFilePathFromUri(context, uri) val path = getFilePathFromUri(context, uri)
@ -460,9 +442,11 @@ object MusicPlayerRemote : KoinComponent {
if (songs != null && songs.isNotEmpty()) { if (songs != null && songs.isNotEmpty()) {
openQueue(songs, 0, true) openQueue(songs, 0, true)
} else { } else {
// TODO the file is not listed in the media store try {
context.showToast(R.string.unplayable_file) context.showToast(R.string.unplayable_file)
println("The file is not listed in the media store") } catch (e: Exception) {
logE("The file is not listed in the media store")
}
} }
} }
} }
@ -472,6 +456,14 @@ object MusicPlayerRemote : KoinComponent {
.dropLastWhile { it.isEmpty() }.toTypedArray()[1] .dropLastWhile { it.isEmpty() }.toTypedArray()[1]
} }
fun switchToRemotePlayback(castSession: CastSession) {
musicService?.switchToRemotePlayback(castSession)
}
fun switchToLocalPlayback() {
musicService?.switchToLocalPlayback()
}
class ServiceBinder internal constructor(private val mCallback: ServiceConnection?) : class ServiceBinder internal constructor(private val mCallback: ServiceConnection?) :
ServiceConnection { ServiceConnection {

View file

@ -15,6 +15,7 @@
package code.name.monkey.retromusic.helper package code.name.monkey.retromusic.helper
import android.os.Handler import android.os.Handler
import android.os.Looper
import android.os.Message import android.os.Message
import kotlin.math.max import kotlin.math.max
@ -32,13 +33,17 @@ class MusicProgressViewUpdateHelper : Handler {
removeMessages(CMD_REFRESH_PROGRESS_VIEWS) removeMessages(CMD_REFRESH_PROGRESS_VIEWS)
} }
constructor(callback: Callback) { constructor(callback: Callback) : super(Looper.getMainLooper()) {
this.callback = callback this.callback = callback
this.intervalPlaying = UPDATE_INTERVAL_PLAYING this.intervalPlaying = UPDATE_INTERVAL_PLAYING
this.intervalPaused = UPDATE_INTERVAL_PAUSED this.intervalPaused = UPDATE_INTERVAL_PAUSED
} }
constructor(callback: Callback, intervalPlaying: Int, intervalPaused: Int) { constructor(
callback: Callback,
intervalPlaying: Int,
intervalPaused: Int,
) : super(Looper.getMainLooper()) {
this.callback = callback this.callback = callback
this.intervalPlaying = intervalPlaying this.intervalPlaying = intervalPlaying
this.intervalPaused = intervalPaused this.intervalPaused = intervalPaused

View file

@ -42,10 +42,11 @@ import kotlin.math.abs
* 歌词 Created by wcy on 2015/11/9. * 歌词 Created by wcy on 2015/11/9.
*/ */
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
@Suppress("deprecation")
class CoverLrcView @JvmOverloads constructor( class CoverLrcView @JvmOverloads constructor(
context: Context?, context: Context?,
attrs: AttributeSet? = null, attrs: AttributeSet? = null,
defStyleAttr: Int = 0 defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr) { ) : View(context, attrs, defStyleAttr) {
private val mLrcEntryList: MutableList<LrcEntry> = ArrayList() private val mLrcEntryList: MutableList<LrcEntry> = ArrayList()
private val mLrcPaint = TextPaint() private val mLrcPaint = TextPaint()
@ -108,7 +109,7 @@ class CoverLrcView @JvmOverloads constructor(
e1: MotionEvent, e1: MotionEvent,
e2: MotionEvent, e2: MotionEvent,
distanceX: Float, distanceX: Float,
distanceY: Float distanceY: Float,
): Boolean { ): Boolean {
if (mOffset == getOffset(0) && distanceY < 0F) { if (mOffset == getOffset(0) && distanceY < 0F) {
return super.onScroll(e1, e2, distanceX, distanceY) return super.onScroll(e1, e2, distanceX, distanceY)
@ -128,7 +129,7 @@ class CoverLrcView @JvmOverloads constructor(
e1: MotionEvent, e1: MotionEvent,
e2: MotionEvent, e2: MotionEvent,
velocityX: Float, velocityX: Float,
velocityY: Float velocityY: Float,
): Boolean { ): Boolean {
if (hasLrc()) { if (hasLrc()) {
mScroller!!.fling( mScroller!!.fling(
@ -256,16 +257,6 @@ class CoverLrcView @JvmOverloads constructor(
postInvalidate() postInvalidate()
} }
/** 普通歌词文本字体大小 */
fun setNormalTextSize(size: Float) {
mNormalTextSize = size
}
/** 当前歌词文本字体大小 */
fun setCurrentTextSize(size: Float) {
mCurrentTextSize = size
}
/** 设置当前行歌词的字体颜色 */ /** 设置当前行歌词的字体颜色 */
fun setCurrentColor(currentColor: Int) { fun setCurrentColor(currentColor: Int) {
mCurrentTextColor = currentColor mCurrentTextColor = currentColor
@ -403,28 +394,6 @@ class CoverLrcView @JvmOverloads constructor(
} }
} }
/**
* 加载在线歌词默认使用 utf-8 编码
*
* @param lrcUrl 歌词文件的网络地址
*/
@JvmOverloads
fun loadLrcByUrl(lrcUrl: String, charset: String? = "utf-8") {
val flag = "url://$lrcUrl"
this.flag = flag
object : AsyncTask<String?, Int?, String>() {
override fun doInBackground(vararg params: String?): String? {
return LrcUtils.getContentFromNetwork(params[0], params[1])
}
override fun onPostExecute(lrcText: String) {
if (flag == flag) {
loadLrc(lrcText)
}
}
}.execute(lrcUrl, charset)
}
/** /**
* 歌词是否有效 * 歌词是否有效
* *
@ -629,7 +598,6 @@ class CoverLrcView @JvmOverloads constructor(
mOffset = animation.animatedValue as Float mOffset = animation.animatedValue as Float
invalidate() invalidate()
} }
LrcUtils.resetDurationScale()
start() start()
} }
} }
@ -711,10 +679,6 @@ class CoverLrcView @JvmOverloads constructor(
fun onPlayClick(time: Long): Boolean fun onPlayClick(time: Long): Boolean
} }
fun interface OnFlingXListener {
fun onFlingX(velocityX: Float): Boolean
}
companion object { companion object {
private const val ADJUST_DURATION: Long = 100 private const val ADJUST_DURATION: Long = 100
private const val TIMELINE_KEEP_TIME = 4 * DateUtils.SECOND_IN_MILLIS private const val TIMELINE_KEEP_TIME = 4 * DateUtils.SECOND_IN_MILLIS

View file

@ -14,7 +14,6 @@
package code.name.monkey.retromusic.lyrics; package code.name.monkey.retromusic.lyrics;
import android.animation.ValueAnimator;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateUtils; import android.text.format.DateUtils;
@ -25,7 +24,6 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -208,14 +206,4 @@ class LrcUtils {
String ss = String.format(Locale.getDefault(), "%02d", s); String ss = String.format(Locale.getDefault(), "%02d", s);
return mm + ":" + ss; return mm + ":" + ss;
} }
static void resetDurationScale() {
try {
Field mField = ValueAnimator.class.getDeclaredField("sDurationScale");
mField.setAccessible(true);
mField.setFloat(null, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
} }

View file

@ -684,7 +684,6 @@ public class LrcView extends View {
mOffset = (float) animation.getAnimatedValue(); mOffset = (float) animation.getAnimatedValue();
invalidate(); invalidate();
}); });
LrcUtils.resetDurationScale();
mAnimator.start(); mAnimator.start();
} }

View file

@ -1,19 +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.misc;
import androidx.core.content.FileProvider;
public class GenericFileProvider extends FileProvider {}

View file

@ -49,7 +49,7 @@ fun headerInterceptor(context: Context): Interceptor {
fun provideOkHttp(context: Context, cache: Cache): OkHttpClient { fun provideOkHttp(context: Context, cache: Cache): OkHttpClient {
return OkHttpClient.Builder() return OkHttpClient.Builder()
.addNetworkInterceptor(logInterceptor()) .addNetworkInterceptor(logInterceptor())
//.addInterceptor(headerInterceptor(context)) .addInterceptor(headerInterceptor(context))
.connectTimeout(1, TimeUnit.SECONDS) .connectTimeout(1, TimeUnit.SECONDS)
.readTimeout(1, TimeUnit.SECONDS) .readTimeout(1, TimeUnit.SECONDS)
.cache(cache) .cache(cache)

View file

@ -61,7 +61,9 @@ class BlacklistPreferenceDialog : DialogFragment(), BlacklistFolderChooserDialog
val chooserDialog = val chooserDialog =
childFragmentManager.findFragmentByTag("FOLDER_CHOOSER") as BlacklistFolderChooserDialog? childFragmentManager.findFragmentByTag("FOLDER_CHOOSER") as BlacklistFolderChooserDialog?
chooserDialog?.setCallback(this) chooserDialog?.setCallback(this)
refreshBlacklistData() val context = requireActivity()
refreshBlacklistData(context)
return materialDialog(R.string.blacklist) return materialDialog(R.string.blacklist)
.setPositiveButton(R.string.done) { _, _ -> .setPositiveButton(R.string.done) { _, _ ->
dismiss() dismiss()
@ -69,7 +71,9 @@ class BlacklistPreferenceDialog : DialogFragment(), BlacklistFolderChooserDialog
.setNeutralButton(R.string.clear_action) { _, _ -> .setNeutralButton(R.string.clear_action) { _, _ ->
materialDialog(R.string.clear_blacklist) materialDialog(R.string.clear_blacklist)
.setMessage(R.string.do_you_want_to_clear_the_blacklist) .setMessage(R.string.do_you_want_to_clear_the_blacklist)
.setPositiveButton(R.string.clear_action, null) .setPositiveButton(R.string.clear_action) { _, _ ->
BlacklistStore.getInstance(context).clear()
}
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.create() .create()
.colorButtons() .colorButtons()
@ -89,9 +93,7 @@ class BlacklistPreferenceDialog : DialogFragment(), BlacklistFolderChooserDialog
).parseAsHtml() ).parseAsHtml()
) )
.setPositiveButton(R.string.remove_action) { _, _ -> .setPositiveButton(R.string.remove_action) { _, _ ->
BlacklistStore.getInstance(requireContext()) BlacklistStore.getInstance(context).removePath(File(paths[which]))
.removePath(File(paths[which]))
refreshBlacklistData()
} }
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.create() .create()
@ -102,23 +104,16 @@ class BlacklistPreferenceDialog : DialogFragment(), BlacklistFolderChooserDialog
setOnShowListener { setOnShowListener {
getButton(AlertDialog.BUTTON_POSITIVE).accentTextColor() getButton(AlertDialog.BUTTON_POSITIVE).accentTextColor()
getButton(AlertDialog.BUTTON_NEGATIVE).accentTextColor() getButton(AlertDialog.BUTTON_NEGATIVE).accentTextColor()
getButton(AlertDialog.BUTTON_NEUTRAL).apply { getButton(AlertDialog.BUTTON_NEUTRAL).accentTextColor()
accentTextColor()
setOnClickListener {
BlacklistStore.getInstance(
requireContext()
).clear()
dismiss()
}
}
} }
} }
} }
private lateinit var paths: ArrayList<String> private lateinit var paths: ArrayList<String>
private fun refreshBlacklistData() { private fun refreshBlacklistData(context: Context?) {
this.paths = BlacklistStore.getInstance(requireContext()).paths if (context == null) return
this.paths = BlacklistStore.getInstance(context).paths
val dialog = dialog as MaterialAlertDialogBuilder? val dialog = dialog as MaterialAlertDialogBuilder?
dialog?.setItems(paths.toTypedArray(), null) dialog?.setItems(paths.toTypedArray(), null)
} }

View file

@ -72,9 +72,11 @@ class RealAlbumRepository(private val songRepository: RealSongRepository) :
// We don't need sorted list of songs (with sortAlbumSongs()) // We don't need sorted list of songs (with sortAlbumSongs())
// cuz we are just displaying Albums(Cover Arts) anyway and not songs // cuz we are just displaying Albums(Cover Arts) anyway and not songs
fun splitIntoAlbums( fun splitIntoAlbums(
songs: List<Song> songs: List<Song>,
sorted: Boolean = true
): List<Album> { ): List<Album> {
val grouped = songs.groupBy { it.albumId }.map { Album(it.key, it.value) } val grouped = songs.groupBy { it.albumId }.map { Album(it.key, it.value) }
if (!sorted) return grouped
val collator = Collator.getInstance() val collator = Collator.getInstance()
return when (PreferenceUtil.albumSortOrder) { return when (PreferenceUtil.albumSortOrder) {
SortOrder.AlbumSortOrder.ALBUM_A_Z -> { SortOrder.AlbumSortOrder.ALBUM_A_Z -> {

View file

@ -42,7 +42,7 @@ class RealLastAddedRepository(
} }
override fun recentAlbums(): List<Album> { override fun recentAlbums(): List<Album> {
return albumRepository.splitIntoAlbums(recentSongs()) return albumRepository.splitIntoAlbums(recentSongs(), sorted = false)
} }
override fun recentArtists(): List<Artist> { override fun recentArtists(): List<Artist> {

View file

@ -28,6 +28,8 @@ import code.name.monkey.retromusic.network.Result.*
import code.name.monkey.retromusic.network.model.LastFmAlbum import code.name.monkey.retromusic.network.model.LastFmAlbum
import code.name.monkey.retromusic.network.model.LastFmArtist import code.name.monkey.retromusic.network.model.LastFmArtist
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.logD
import code.name.monkey.retromusic.util.logE
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -103,7 +105,6 @@ interface Repository {
suspend fun clearSongHistory() suspend fun clearSongHistory()
suspend fun checkSongExistInPlayCount(songId: Long): List<PlayCountEntity> suspend fun checkSongExistInPlayCount(songId: Long): List<PlayCountEntity>
suspend fun playCountSongs(): List<PlayCountEntity> suspend fun playCountSongs(): List<PlayCountEntity>
suspend fun blackListPaths(): List<BlackListStoreEntity>
suspend fun deleteSongs(songs: List<Song>) suspend fun deleteSongs(songs: List<Song>)
suspend fun contributor(): List<Contributor> suspend fun contributor(): List<Contributor>
suspend fun searchArtists(query: String): List<Artist> suspend fun searchArtists(query: String): List<Artist>
@ -195,7 +196,7 @@ class RealRepository(
return try { return try {
Success(lastFMService.artistInfo(name, lang, cache)) Success(lastFMService.artistInfo(name, lang, cache))
} catch (e: Exception) { } catch (e: Exception) {
println(e) logE(e)
Error(e) Error(e)
} }
} }
@ -208,7 +209,7 @@ class RealRepository(
val lastFmAlbum = lastFMService.albumInfo(artist, album) val lastFmAlbum = lastFMService.albumInfo(artist, album)
Success(lastFmAlbum) Success(lastFmAlbum)
} catch (e: Exception) { } catch (e: Exception) {
println(e) logE(e)
Error(e) Error(e)
} }
} }
@ -228,7 +229,7 @@ class RealRepository(
) )
for (section in sections) { for (section in sections) {
if (section.arrayList.isNotEmpty()) { if (section.arrayList.isNotEmpty()) {
println("${section.homeSection} -> ${section.arrayList.size}") logD("${section.homeSection} -> ${section.arrayList.size}")
homeSections.add(section) homeSections.add(section)
} }
} }
@ -345,9 +346,6 @@ class RealRepository(
override suspend fun playCountSongs(): List<PlayCountEntity> = override suspend fun playCountSongs(): List<PlayCountEntity> =
roomRepository.playCountSongs() roomRepository.playCountSongs()
override suspend fun blackListPaths(): List<BlackListStoreEntity> =
roomRepository.blackListPaths()
override fun observableHistorySongs(): LiveData<List<Song>> = override fun observableHistorySongs(): LiveData<List<Song>> =
Transformations.map(roomRepository.observableHistorySongs()) { Transformations.map(roomRepository.observableHistorySongs()) {
it.fromHistoryToSongs() it.fromHistoryToSongs()
@ -381,7 +379,6 @@ class RealRepository(
} }
override suspend fun suggestions(): List<Song> { override suspend fun suggestions(): List<Song> {
if (!PreferenceUtil.homeSuggestions) return listOf()
return NotPlayedPlaylist().songs().shuffled().takeIf { return NotPlayedPlaylist().songs().shuffled().takeIf {
it.size > 9 it.size > 9
} ?: emptyList() } ?: emptyList()

View file

@ -16,7 +16,6 @@ import code.name.monkey.retromusic.util.PreferenceUtil
interface RoomRepository { interface RoomRepository {
fun historySongs(): List<HistoryEntity> fun historySongs(): List<HistoryEntity>
fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>> fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>>
fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
fun observableHistorySongs(): LiveData<List<HistoryEntity>> fun observableHistorySongs(): LiveData<List<HistoryEntity>>
fun getSongs(playListId: Long): LiveData<List<SongEntity>> fun getSongs(playListId: Long): LiveData<List<SongEntity>>
suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long
@ -42,11 +41,6 @@ interface RoomRepository {
suspend fun clearSongHistory() suspend fun clearSongHistory()
suspend fun checkSongExistInPlayCount(songId: Long): List<PlayCountEntity> suspend fun checkSongExistInPlayCount(songId: Long): List<PlayCountEntity>
suspend fun playCountSongs(): List<PlayCountEntity> suspend fun playCountSongs(): List<PlayCountEntity>
suspend fun insertBlacklistPath(blackListStoreEntities: List<BlackListStoreEntity>)
suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
suspend fun clearBlacklist()
suspend fun insertBlacklistPathAsync(blackListStoreEntity: BlackListStoreEntity)
suspend fun blackListPaths(): List<BlackListStoreEntity>
suspend fun deleteSongs(songs: List<Song>) suspend fun deleteSongs(songs: List<Song>)
suspend fun isSongFavorite(context: Context, songId: Long): Boolean suspend fun isSongFavorite(context: Context, songId: Long): Boolean
fun checkPlaylistExists(playListId: Long): LiveData<Boolean> fun checkPlaylistExists(playListId: Long): LiveData<Boolean>
@ -54,10 +48,8 @@ interface RoomRepository {
class RealRoomRepository( class RealRoomRepository(
private val playlistDao: PlaylistDao, private val playlistDao: PlaylistDao,
private val blackListStoreDao: BlackListStoreDao,
private val playCountDao: PlayCountDao, private val playCountDao: PlayCountDao,
private val historyDao: HistoryDao, private val historyDao: HistoryDao
private val lyricsDao: LyricsDao
) : RoomRepository { ) : RoomRepository {
@WorkerThread @WorkerThread
override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long = override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long =
@ -123,7 +115,6 @@ class RealRoomRepository(
return if (playlist != null) { return if (playlist != null) {
playlist playlist
} else { } else {
println("Playlist Created")
createPlaylist(PlaylistEntity(playlistName = favorite)) createPlaylist(PlaylistEntity(playlistName = favorite))
playlistDao.playlist(favorite).first() playlistDao.playlist(favorite).first()
} }
@ -185,27 +176,10 @@ class RealRoomRepository(
override suspend fun playCountSongs(): List<PlayCountEntity> = override suspend fun playCountSongs(): List<PlayCountEntity> =
playCountDao.playCountSongs() playCountDao.playCountSongs()
override fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity) =
blackListStoreDao.insertBlacklistPath(blackListStoreEntity)
override suspend fun insertBlacklistPath(blackListStoreEntities: List<BlackListStoreEntity>) =
blackListStoreDao.insertBlacklistPath(blackListStoreEntities)
override suspend fun insertBlacklistPathAsync(blackListStoreEntity: BlackListStoreEntity) =
blackListStoreDao.insertBlacklistPath(blackListStoreEntity)
override suspend fun blackListPaths(): List<BlackListStoreEntity> =
blackListStoreDao.blackListPaths()
override suspend fun deleteSongs(songs: List<Song>) = songs.forEach { override suspend fun deleteSongs(songs: List<Song>) = songs.forEach {
playCountDao.deleteSong(it.id) playCountDao.deleteSong(it.id)
} }
override suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity) =
blackListStoreDao.deleteBlacklistPath(blackListStoreEntity)
override suspend fun clearBlacklist() = blackListStoreDao.clearBlacklist()
override suspend fun isSongFavorite(context: Context, songId: Long): Boolean { override suspend fun isSongFavorite(context: Context, songId: Long): Boolean {
return playlistDao.isSongExistsInPlaylist( return playlistDao.isSongExistsInPlaylist(
playlistDao.playlist(context.getString(R.string.favorites)).firstOrNull()?.playListId playlistDao.playlist(context.getString(R.string.favorites)).firstOrNull()?.playListId

View file

@ -81,7 +81,7 @@ class RealTopPlayedRepository(
} }
override fun topAlbums(): List<Album> { override fun topAlbums(): List<Album> {
return albumRepository.splitIntoAlbums(topTracks()) return albumRepository.splitIntoAlbums(topTracks(), sorted = false)
} }
override fun topArtists(): List<Artist> { override fun topArtists(): List<Artist> {

View file

@ -12,9 +12,9 @@ class AudioFader {
@JvmStatic @JvmStatic
inline fun createFadeAnimator( inline fun createFadeAnimator(
fadeIn: Boolean /* fadeIn -> true fadeOut -> false*/, fadeIn: Boolean, /* fadeIn -> true fadeOut -> false*/
mediaPlayer: MediaPlayer, mediaPlayer: MediaPlayer,
crossinline endAction: (animator: Animator) -> Unit /* Code to run when Animator Ends*/ crossinline endAction: (animator: Animator) -> Unit, /* Code to run when Animator Ends*/
): Animator? { ): Animator? {
val duration = PreferenceUtil.crossFadeDuration * 1000 val duration = PreferenceUtil.crossFadeDuration * 1000
if (duration == 0) { if (duration == 0) {
@ -40,8 +40,8 @@ class AudioFader {
@JvmStatic @JvmStatic
fun startFadeAnimator( fun startFadeAnimator(
playback: Playback, playback: Playback,
fadeIn: Boolean /* fadeIn -> true fadeOut -> false*/, fadeIn: Boolean, /* fadeIn -> true fadeOut -> false*/
callback: Runnable /* Code to run when Animator Ends*/ callback: Runnable, /* Code to run when Animator Ends*/
) { ) {
val duration = PreferenceUtil.audioFadeDuration.toLong() val duration = PreferenceUtil.audioFadeDuration.toLong()
if (duration == 0L) { if (duration == 0L) {

View file

@ -0,0 +1,115 @@
package code.name.monkey.retromusic.service
import code.name.monkey.retromusic.cast.CastHelper.toMediaInfo
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.playback.Playback
import code.name.monkey.retromusic.util.PreferenceUtil.playbackSpeed
import com.google.android.gms.cast.MediaLoadOptions
import com.google.android.gms.cast.MediaSeekOptions
import com.google.android.gms.cast.MediaStatus
import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.media.RemoteMediaClient
class CastPlayer(castSession: CastSession) : Playback,
RemoteMediaClient.Callback() {
override val isInitialized: Boolean = true
private val remoteMediaClient: RemoteMediaClient? = castSession.remoteMediaClient
init {
remoteMediaClient?.registerCallback(this)
remoteMediaClient?.setPlaybackRate(playbackSpeed.toDouble().coerceIn(0.5, 2.0))
}
private var isActuallyPlaying = false
override val isPlaying: Boolean
get() {
return remoteMediaClient?.isPlaying == true || isActuallyPlaying
}
override val audioSessionId: Int = 0
private var callbacks: Playback.PlaybackCallbacks? = null
override fun setDataSource(
song: Song,
force: Boolean,
completion: (success: Boolean) -> Unit,
) {
try {
val mediaLoadOptions =
MediaLoadOptions.Builder().setPlayPosition(0).setAutoplay(true).build()
remoteMediaClient?.load(song.toMediaInfo()!!, mediaLoadOptions)
completion(true)
} catch (e: Exception) {
e.printStackTrace()
completion(false)
}
}
override fun setNextDataSource(path: String?) {}
override fun setCallbacks(callbacks: Playback.PlaybackCallbacks) {
this.callbacks = callbacks
}
override fun start(): Boolean {
isActuallyPlaying = true
remoteMediaClient?.play()
return true
}
override fun stop() {
isActuallyPlaying = false
remoteMediaClient?.stop()
}
override fun release() {
stop()
}
override fun pause(): Boolean {
isActuallyPlaying = false
remoteMediaClient?.pause()
return true
}
override fun duration(): Int {
return remoteMediaClient?.streamDuration?.toInt() ?: 0
}
override fun position(): Int {
return remoteMediaClient?.approximateStreamPosition?.toInt() ?: 0
}
override fun seek(whereto: Int): Int {
remoteMediaClient?.seek(MediaSeekOptions.Builder().setPosition(whereto.toLong()).build())
return whereto
}
override fun setVolume(vol: Float) = true
override fun setAudioSessionId(sessionId: Int) = true
override fun setCrossFadeDuration(duration: Int) {}
override fun setPlaybackSpeedPitch(speed: Float, pitch: Float) {
remoteMediaClient?.setPlaybackRate(speed.toDouble().coerceIn(0.5, 2.0))
}
override fun onStatusUpdated() {
when (remoteMediaClient?.playerState) {
MediaStatus.PLAYER_STATE_IDLE -> {
val idleReason = remoteMediaClient.idleReason
if (idleReason == MediaStatus.IDLE_REASON_FINISHED) {
callbacks?.onTrackEnded()
}
}
MediaStatus.PLAYER_STATE_PLAYING, MediaStatus.PLAYER_STATE_PAUSED -> {
callbacks?.onPlayStateChanged()
}
}
}
}

View file

@ -2,26 +2,23 @@ package code.name.monkey.retromusic.service
import android.animation.Animator import android.animation.Animator
import android.content.Context import android.content.Context
import android.content.Intent
import android.media.AudioAttributes import android.media.AudioAttributes
import android.media.AudioManager import android.media.AudioManager
import android.media.MediaPlayer import android.media.MediaPlayer
import android.media.PlaybackParams import android.media.PlaybackParams
import android.media.audiofx.AudioEffect
import android.os.PowerManager import android.os.PowerManager
import android.util.Log import android.util.Log
import androidx.core.net.toUri import androidx.core.net.toUri
import code.name.monkey.appthemehelper.util.VersionUtils.hasMarshmallow import code.name.monkey.appthemehelper.util.VersionUtils.hasMarshmallow
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.extensions.uri
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.AudioFader.Companion.createFadeAnimator import code.name.monkey.retromusic.service.AudioFader.Companion.createFadeAnimator
import code.name.monkey.retromusic.service.playback.Playback import code.name.monkey.retromusic.service.playback.Playback
import code.name.monkey.retromusic.service.playback.Playback.PlaybackCallbacks import code.name.monkey.retromusic.service.playback.Playback.PlaybackCallbacks
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.PreferenceUtil.playbackPitch
import code.name.monkey.retromusic.util.PreferenceUtil.playbackSpeed
import kotlinx.coroutines.* import kotlinx.coroutines.*
/** @author Prathamesh M */ /** @author Prathamesh M */
@ -124,18 +121,27 @@ class CrossFadePlayer(val context: Context) : Playback, MediaPlayer.OnCompletion
override val isPlaying: Boolean override val isPlaying: Boolean
get() = mIsInitialized && getCurrentPlayer()?.isPlaying == true get() = mIsInitialized && getCurrentPlayer()?.isPlaying == true
override fun setDataSource(path: String, force: Boolean): Boolean { override fun setDataSource(
song: Song,
force: Boolean,
completion: (success: Boolean) -> Unit,
) {
cancelFade() cancelFade()
if (force) hasDataSource = false if (force) hasDataSource = false
mIsInitialized = false mIsInitialized = false
/* We've already set DataSource if initialized is true in setNextDataSource */ /* We've already set DataSource if initialized is true in setNextDataSource */
if (!hasDataSource) { if (!hasDataSource) {
getCurrentPlayer()?.let { mIsInitialized = setDataSourceImpl(it, path) } getCurrentPlayer()?.let {
setDataSourceImpl(it, song.uri.toString()) { success ->
mIsInitialized = success
completion(success)
}
}
hasDataSource = true hasDataSource = true
} else { } else {
completion(true)
mIsInitialized = true mIsInitialized = true
} }
return mIsInitialized
} }
override fun setNextDataSource(path: String?) {} override fun setNextDataSource(path: String?) {}
@ -148,9 +154,9 @@ class CrossFadePlayer(val context: Context) : Playback, MediaPlayer.OnCompletion
private fun setDataSourceImpl( private fun setDataSourceImpl(
player: MediaPlayer, player: MediaPlayer,
path: String, path: String,
): Boolean { completion: (success: Boolean) -> Unit,
) {
player.reset() player.reset()
player.setOnPreparedListener(null)
try { try {
if (path.startsWith("content://")) { if (path.startsWith("content://")) {
player.setDataSource(context, path.toUri()) player.setDataSource(context, path.toUri())
@ -160,20 +166,17 @@ class CrossFadePlayer(val context: Context) : Playback, MediaPlayer.OnCompletion
player.setAudioAttributes( player.setAudioAttributes(
AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_MUSIC).build() AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_MUSIC).build()
) )
player.prepare() player.setOnPreparedListener {
player.setPlaybackSpeedPitch(playbackSpeed, playbackPitch) player.setOnPreparedListener(null)
completion(true)
}
player.prepareAsync()
} catch (e: Exception) { } catch (e: Exception) {
completion(false)
e.printStackTrace() e.printStackTrace()
return false
} }
player.setOnCompletionListener(this) player.setOnCompletionListener(this)
player.setOnErrorListener(this) player.setOnErrorListener(this)
val intent = Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION)
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, audioSessionId)
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.packageName)
intent.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC)
context.sendBroadcast(intent)
return true
} }
override fun setAudioSessionId(sessionId: Int): Boolean { override fun setAudioSessionId(sessionId: Int): Boolean {
@ -315,15 +318,15 @@ class CrossFadePlayer(val context: Context) : Playback, MediaPlayer.OnCompletion
} }
} }
fun onDurationUpdated(progress: Int, total: Int) { fun onDurationUpdated(progress: Int, total: Int) {
if (total > 0 && (total - progress).div(1000) == crossFadeDuration) { if (total > 0 && (total - progress).div(1000) == crossFadeDuration) {
getNextPlayer()?.let { player -> getNextPlayer()?.let { player ->
val nextSong = MusicPlayerRemote.nextSong val nextSong = MusicPlayerRemote.nextSong
if (nextSong != null) { if (nextSong != null) {
setDataSourceImpl(player, MusicUtil.getSongFileUri(nextSong.id).toString()) setDataSourceImpl(player, nextSong.uri.toString()) { success ->
// Switch to other player / Crossfade only if next song exists // Switch to other player (Crossfade) only if next song exists
switchPlayer() if (success) switchPlayer()
}
} }
} }
} }
@ -348,15 +351,8 @@ class CrossFadePlayer(val context: Context) : Playback, MediaPlayer.OnCompletion
override fun setPlaybackSpeedPitch(speed: Float, pitch: Float) { override fun setPlaybackSpeedPitch(speed: Float, pitch: Float) {
getCurrentPlayer()?.setPlaybackSpeedPitch(speed, pitch) getCurrentPlayer()?.setPlaybackSpeedPitch(speed, pitch)
} if (getNextPlayer()?.isPlaying == true) {
getNextPlayer()?.setPlaybackSpeedPitch(speed, pitch)
private fun MediaPlayer.setPlaybackSpeedPitch(speed: Float, pitch: Float) {
if (hasMarshmallow()) {
val wasPlaying: Boolean = isPlaying
playbackParams = PlaybackParams().setSpeed(speed).setPitch(pitch)
if (!wasPlaying) {
if (isPlaying) pause()
}
} }
} }
@ -366,3 +362,9 @@ class CrossFadePlayer(val context: Context) : Playback, MediaPlayer.OnCompletion
} }
internal fun crossFadeScope(): CoroutineScope = CoroutineScope(Job() + Dispatchers.Main) internal fun crossFadeScope(): CoroutineScope = CoroutineScope(Job() + Dispatchers.Main)
fun MediaPlayer.setPlaybackSpeedPitch(speed: Float, pitch: Float) {
if (hasMarshmallow()) {
playbackParams = PlaybackParams().setSpeed(speed).setPitch(pitch)
}
}

View file

@ -14,7 +14,6 @@
package code.name.monkey.retromusic.service package code.name.monkey.retromusic.service
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore import android.provider.MediaStore
import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.MediaSessionCompat
@ -31,6 +30,8 @@ import code.name.monkey.retromusic.service.MusicService.Companion.CYCLE_REPEAT
import code.name.monkey.retromusic.service.MusicService.Companion.TOGGLE_FAVORITE import code.name.monkey.retromusic.service.MusicService.Companion.TOGGLE_FAVORITE
import code.name.monkey.retromusic.service.MusicService.Companion.TOGGLE_SHUFFLE import code.name.monkey.retromusic.service.MusicService.Companion.TOGGLE_SHUFFLE
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.logD
import code.name.monkey.retromusic.util.logE
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
@ -39,7 +40,6 @@ import org.koin.core.component.inject
*/ */
class MediaSessionCallback( class MediaSessionCallback(
private val context: Context,
private val musicService: MusicService private val musicService: MusicService
) : MediaSessionCompat.Callback(), KoinComponent { ) : MediaSessionCompat.Callback(), KoinComponent {
@ -53,7 +53,7 @@ class MediaSessionCallback(
override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) { override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) {
super.onPlayFromMediaId(mediaId, extras) super.onPlayFromMediaId(mediaId, extras)
val musicId = AutoMediaIDHelper.extractMusicID(mediaId!!) val musicId = AutoMediaIDHelper.extractMusicID(mediaId!!)
println(musicId) logD(musicId)
val itemId = musicId?.toLong() ?: -1 val itemId = musicId?.toLong() ?: -1
val songs: ArrayList<Song> = ArrayList() val songs: ArrayList<Song> = ArrayList()
when (val category = AutoMediaIDHelper.extractCategory(mediaId)) { when (val category = AutoMediaIDHelper.extractCategory(mediaId)) {
@ -165,7 +165,7 @@ class MediaSessionCallback(
override fun onSkipToPrevious() { override fun onSkipToPrevious() {
super.onSkipToPrevious() super.onSkipToPrevious()
musicService.back(true) musicService.playPreviousSong(true)
} }
override fun onStop() { override fun onStop() {
@ -190,11 +190,10 @@ class MediaSessionCallback(
musicService.updateMediaSessionPlaybackState() musicService.updateMediaSessionPlaybackState()
} }
TOGGLE_FAVORITE -> { TOGGLE_FAVORITE -> {
MusicUtil.toggleFavorite(context, MusicPlayerRemote.currentSong) musicService.toggleFavorite()
musicService.updateMediaSessionPlaybackState()
} }
else -> { else -> {
println("Unsupported action: $action") logE("Unsupported action: $action")
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show more