Merge pull request #1371 from prathameshmm02/dev

V6 beta
This commit is contained in:
Daksh P. Jain 2022-06-08 09:15:17 +05:30 committed by GitHub
commit 477948a495
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
257 changed files with 3514 additions and 4270 deletions

View file

@ -14,8 +14,8 @@ android {
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
applicationId "code.name.monkey.retromusic" applicationId "code.name.monkey.retromusic"
versionCode 10584 versionCode 10590
versionName '5.8.4' versionName '6.0.0-beta'
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
@ -87,13 +86,13 @@ static def getDate() {
dependencies { dependencies {
implementation project(':appthemehelper') implementation project(':appthemehelper')
implementation "androidx.gridlayout:gridlayout:1.0.0" implementation "androidx.gridlayout:gridlayout: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.8.0'
implementation 'androidx.palette:palette-ktx:1.0.0' implementation 'androidx.palette:palette-ktx:1.0.0'
//Cast Dependencies //Cast Dependencies
@ -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'
@ -135,7 +136,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
def kotlin_coroutines_version = '1.6.1' def kotlin_coroutines_version = '1.6.2'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
@ -164,7 +165,7 @@ dependencies {
implementation 'com.heinrichreimersoftware:material-intro:2.0.0' implementation 'com.heinrichreimersoftware:material-intro:2.0.0'
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.4.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"
@ -36,13 +39,13 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.RetroMusic.FollowSystem" android:theme="@style/Theme.RetroMusic.FollowSystem"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
tools:ignore="AllowBackup,GoogleAppIndexingWarning" android:requestLegacyExternalStorage="true"
tools:targetApi="m"> tools:targetApi="m">
<activity <activity
android:name=".activities.MainActivity" android:name=".activities.MainActivity"
android:exported="true" android:exported="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/SplashTheme"> android:theme="@style/Theme.RetroMusic.SplashScreen">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.MUSIC_PLAYER" /> <action android:name="android.intent.action.MUSIC_PLAYER" />
@ -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,24 @@
</head> </head>
<body> <body>
<div>
<h5>June 7, 2022</h5>
<h2>v6.0.0<span class="tag"><i>Beta</i></span></h2>
<h3>What's New</h3>
<ul>
<li>Better Cast</li>
<li>Mini player in settings screen</li>
<li>Changed Seekbar with Sliders</li>
<li>Added NavigationRailView for Landscape</li>
<li>Show remaining time in Sleep timer dialog</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fixed Top/Recent Artists/Albums not updating (Wrong sort order)</li>
<li>Fixed all Blacklist related crashes</li>
<li>Fix restart button not working in crash activity</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

@ -15,11 +15,13 @@
package code.name.monkey.retromusic package code.name.monkey.retromusic
import android.app.Application import android.app.Application
import androidx.preference.PreferenceManager
import cat.ereza.customactivityoncrash.config.CaocConfig import cat.ereza.customactivityoncrash.config.CaocConfig
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.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 +71,12 @@ 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()
// Set Default values for now playing preferences
// This will reduce start time for now playing settings fragment as Preference listener of AbsSlidingMusicPanelActivity won't be called
PreferenceManager.setDefaultValues(this, R.xml.pref_now_playing_screen, false)
} }
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.toInt())
MusicPlayerRemote.seekTo(progress) 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,17 +15,14 @@
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.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
@ -36,20 +33,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() {
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 +52,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)
} }
@ -86,9 +78,9 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
) )
} }
navController.graph = navGraph navController.graph = navGraph
bottomNavigationView.setupWithNavController(navController) navigationView.setupWithNavController(navController)
// Scroll Fragment to top // Scroll Fragment to top
bottomNavigationView.setOnItemReselectedListener { navigationView.setOnItemReselectedListener {
currentFragment(R.id.fragment_container).apply { currentFragment(R.id.fragment_container).apply {
if (this is IScrollHelper) { if (this is IScrollHelper) {
scrollToTop() scrollToTop()
@ -120,7 +112,9 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
} }
private fun saveTab(id: Int) { private fun saveTab(id: Int) {
PreferenceUtil.lastTab = id if (PreferenceUtil.libraryCategory.firstOrNull { it.category.id == id }?.visible == true) {
PreferenceUtil.lastTab = id
}
} }
override fun onSupportNavigateUp(): Boolean = override fun onSupportNavigateUp(): Boolean =
@ -137,22 +131,6 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
} }
} }
override fun onResume() {
super.onResume()
PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
}
override fun onDestroy() {
super.onDestroy()
PreferenceUtil.unregisterOnSharedPreferenceChangedListener(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()
}
}
override fun onServiceConnected() { override fun onServiceConnected() {
super.onServiceConnected() super.onServiceConnected()
intent ?: return intent ?: return
@ -220,7 +198,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 +207,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,8 +63,10 @@ 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)
} }
} else {
binding.audioPermission.setNumber("2")
} }
binding.finish.accentBackgroundColor() binding.finish.accentBackgroundColor()

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,15 @@ 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.bottomnavigation.BottomNavigationView
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 +82,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,45 +97,47 @@ 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)
navigationBarColorAnimator?.cancel() navigationBarColorAnimator?.cancel()
setNavigationBarColorPreOreo( setNavigationBarColorPreOreo(
argbEvaluator.evaluate( argbEvaluator.evaluate(
slideOffset, slideOffset,
surfaceColor(), surfaceColor(),
navigationBarColor navigationBarColor
) as Int ) as Int
) )
} }
override fun onStateChanged(bottomSheet: View, newState: Int) { override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) { when (newState) {
STATE_EXPANDED -> { STATE_EXPANDED -> {
onPanelExpanded() onPanelExpanded()
if (PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) { if (PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) {
keepScreenOn(true) keepScreenOn(true)
}
} }
} STATE_COLLAPSED -> {
STATE_COLLAPSED -> { onPanelCollapsed()
onPanelCollapsed() if ((PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) || !PreferenceUtil.isScreenOnEnabled) {
if ((PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) || !PreferenceUtil.isScreenOnEnabled) { keepScreenOn(false)
keepScreenOn(false) }
} }
} STATE_SETTLING, STATE_DRAGGING -> {
STATE_SETTLING, STATE_DRAGGING -> { if (fromNotification) {
if (fromNotification) { binding.navigationView.bringToFront()
binding.bottomNavigationView.bringToFront() fromNotification = false
fromNotification = false }
}
STATE_HIDDEN -> {
MusicPlayerRemote.clearQueue()
}
else -> {
logD("Do a flip")
} }
}
STATE_HIDDEN -> {
MusicPlayerRemote.clearQueue()
}
else -> {
println("Do a flip")
} }
} }
} }
@ -137,12 +147,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()
@ -151,7 +163,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
updateColor() updateColor()
if (!PreferenceUtil.materialYou) { if (!PreferenceUtil.materialYou) {
binding.slidingPanel.backgroundTintList = ColorStateList.valueOf(darkAccentColor()) binding.slidingPanel.backgroundTintList = ColorStateList.valueOf(darkAccentColor())
bottomNavigationView.backgroundTintList = ColorStateList.valueOf(darkAccentColor()) navigationView.backgroundTintList = ColorStateList.valueOf(darkAccentColor())
} }
navigationBarColor = surfaceColor() navigationBarColor = surfaceColor()
@ -166,6 +178,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 +190,60 @@ 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 -> {
chooseFragmentForTheme()
binding.slidingPanel.updateLayoutParams<ViewGroup.LayoutParams> {
height = if (nowPlayingScreen != Peek) {
ViewGroup.LayoutParams.MATCH_PARENT
} else {
ViewGroup.LayoutParams.WRAP_CONTENT
}
onServiceConnected()
}
}
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 -> {
navigationView.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() {
@ -196,8 +259,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
val alpha = 1 - progress val alpha = 1 - progress
miniPlayerFragment?.view?.alpha = 1 - (progress / 0.2F) miniPlayerFragment?.view?.alpha = 1 - (progress / 0.2F)
miniPlayerFragment?.view?.isGone = alpha == 0f miniPlayerFragment?.view?.isGone = alpha == 0f
binding.bottomNavigationView.translationY = progress * 500 if (!isLandscape) {
binding.bottomNavigationView.alpha = alpha binding.navigationView.translationY = progress * 500
binding.navigationView.alpha = alpha
}
binding.playerFragmentContainer.alpha = (progress - 0.2F) / 0.2F binding.playerFragmentContainer.alpha = (progress - 0.2F) / 0.2F
} }
@ -224,13 +289,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() {
@ -254,21 +319,15 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
}) })
} }
val bottomNavigationView get() = binding.bottomNavigationView val navigationView get() = binding.navigationView
val slidingPanel get() = binding.slidingPanel val slidingPanel get() = binding.slidingPanel
val isBottomNavVisible get() = navigationView.isVisible && navigationView is BottomNavigationView
override fun onServiceConnected() { override fun onServiceConnected() {
super.onServiceConnected() super.onServiceConnected()
if (MusicPlayerRemote.playingQueue.isNotEmpty()) { hideBottomSheet(false)
binding.slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
binding.slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
hideBottomSheet(false)
}
})
} // don't call hideBottomSheet(true) here as it causes a bug with the SlidingUpPanelLayout
} }
override fun onQueueChanged() { override fun onQueueChanged() {
@ -285,7 +344,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
@ -332,18 +391,20 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} }
fun updateTabs() { fun updateTabs() {
binding.bottomNavigationView.menu.clear() binding.navigationView.menu.clear()
val currentTabs: List<CategoryInfo> = PreferenceUtil.libraryCategory val currentTabs: List<CategoryInfo> = PreferenceUtil.libraryCategory
for (tab in currentTabs) { for (tab in currentTabs) {
if (tab.visible) { if (tab.visible) {
val menu = tab.category val menu = tab.category
binding.bottomNavigationView.menu.add(0, menu.id, 0, menu.stringRes) binding.navigationView.menu.add(0, menu.id, 0, menu.stringRes)
.setIcon(menu.icon) .setIcon(menu.icon)
} }
} }
if (binding.bottomNavigationView.menu.size() == 1) { if (binding.navigationView.menu.size() == 1) {
isInOneTabMode = true isInOneTabMode = true
binding.bottomNavigationView.hide() binding.navigationView.isVisible = false
} else {
isInOneTabMode = false
} }
} }
@ -367,38 +428,38 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
) )
return return
} }
val mAnimate = animate && bottomSheetBehavior.state == STATE_COLLAPSED if (visible xor navigationView.isVisible) {
if (mAnimate) { val mAnimate = animate && bottomSheetBehavior.state == STATE_COLLAPSED
if (visible) { if (mAnimate) {
binding.bottomNavigationView.bringToFront() if (visible) {
binding.bottomNavigationView.show() binding.navigationView.bringToFront()
binding.navigationView.show()
} else {
binding.navigationView.hide()
}
} else { } else {
binding.bottomNavigationView.hide() binding.navigationView.isVisible = visible
} if (visible && bottomSheetBehavior.state != STATE_EXPANDED) {
} else { binding.navigationView.bringToFront()
binding.bottomNavigationView.isVisible = false }
if (visible && bottomSheetBehavior.state != STATE_EXPANDED) {
binding.bottomNavigationView.bringToFront()
} }
} }
hideBottomSheet( hideBottomSheet(
hide = hideBottomSheet, hide = hideBottomSheet,
animate = animate, animate = animate,
isBottomNavVisible = visible isBottomNavVisible = visible && navigationView is BottomNavigationView
) )
} }
fun hideBottomSheet( fun hideBottomSheet(
hide: Boolean, hide: Boolean,
animate: Boolean = false, animate: Boolean = false,
isBottomNavVisible: Boolean = bottomNavigationView.isVisible, isBottomNavVisible: Boolean = navigationView.isVisible && navigationView is BottomNavigationView,
) { ) {
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,
@ -407,17 +468,18 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} else { } else {
if (MusicPlayerRemote.playingQueue.isNotEmpty()) { if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
binding.slidingPanel.elevation = 0F binding.slidingPanel.elevation = 0F
binding.bottomNavigationView.elevation = 5F binding.navigationView.elevation = 5F
if (isBottomNavVisible) { if (isBottomNavVisible) {
println("List") logD("List")
if (animate) { if (animate) {
bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs) bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs)
} else { } else {
bottomSheetBehavior.peekHeight = heightOfBarWithTabs bottomSheetBehavior.peekHeight = heightOfBarWithTabs
} }
libraryViewModel.setFabMargin(this, dip(R.dimen.mini_player_height_expanded)) libraryViewModel.setFabMargin(this,
dip(R.dimen.bottom_nav_mini_player_height))
} 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 +502,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 +522,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
@ -43,13 +43,13 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
hideStatusBar() hideStatusBar()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
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 +61,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 +74,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 +85,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

@ -159,6 +159,7 @@ open class SongAdapter(
override fun getPopupText(position: Int): String { override fun getPopupText(position: Int): String {
val sectionName: String? = when (PreferenceUtil.songSortOrder) { val sectionName: String? = when (PreferenceUtil.songSortOrder) {
SortOrder.SongSortOrder.SONG_DEFAULT -> return MusicUtil.getSectionName(dataSet[position].title, true)
SortOrder.SongSortOrder.SONG_A_Z, SortOrder.SongSortOrder.SONG_Z_A -> dataSet[position].title SortOrder.SongSortOrder.SONG_A_Z, SortOrder.SongSortOrder.SONG_Z_A -> dataSet[position].title
SortOrder.SongSortOrder.SONG_ALBUM -> dataSet[position].albumName SortOrder.SongSortOrder.SONG_ALBUM -> dataSet[position].albumName
SortOrder.SongSortOrder.SONG_ARTIST -> dataSet[position].artistName SortOrder.SongSortOrder.SONG_ARTIST -> dataSet[position].artistName

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

@ -59,8 +59,9 @@ interface PlaylistDao {
@Delete @Delete
suspend fun deletePlaylistSongs(songs: List<SongEntity>) suspend fun deletePlaylistSongs(songs: List<SongEntity>)
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId") @RewriteQueriesToDropUnusedColumns
fun favoritesSongsLiveData(playlistId: Long): LiveData<List<SongEntity>> @Query("SELECT * FROM SongEntity ,(SELECT playlist_id FROM PlaylistEntity WHERE playlist_name= :playlistName LIMIT 1) AS playlist WHERE playlist_creator_id= playlist.playlist_id")
fun favoritesSongsLiveData(playlistName: String): LiveData<List<SongEntity>>
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId") @Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId")
fun favoritesSongs(playlistId: Long): List<SongEntity> fun favoritesSongs(playlistId: Long): List<SongEntity>

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

@ -17,6 +17,7 @@ package code.name.monkey.retromusic.dialogs
import android.app.AlarmManager import android.app.AlarmManager
import android.app.Dialog import android.app.Dialog
import android.app.PendingIntent import android.app.PendingIntent
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.CountDownTimer import android.os.CountDownTimer
@ -25,43 +26,45 @@ import android.widget.CheckBox
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.view.isVisible
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
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.databinding.DialogSleepTimerBinding import code.name.monkey.retromusic.databinding.DialogSleepTimerBinding
import code.name.monkey.retromusic.extensions.addAccentColor import code.name.monkey.retromusic.extensions.addAccentColor
import code.name.monkey.retromusic.extensions.colorButtons
import code.name.monkey.retromusic.extensions.materialDialog import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.service.MusicService.Companion.ACTION_PENDING_QUIT import code.name.monkey.retromusic.service.MusicService.Companion.ACTION_PENDING_QUIT
import code.name.monkey.retromusic.service.MusicService.Companion.ACTION_QUIT import code.name.monkey.retromusic.service.MusicService.Companion.ACTION_QUIT
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.WhichButton
import com.afollestad.materialdialogs.actions.getActionButton
class SleepTimerDialog : DialogFragment() { class SleepTimerDialog : DialogFragment() {
private var seekArcProgress: Int = 0 private var seekArcProgress: Int = 0
private lateinit var timerUpdater: TimerUpdater private lateinit var timerUpdater: TimerUpdater
private lateinit var dialog: MaterialDialog private lateinit var dialog: AlertDialog
private lateinit var shouldFinishLastSong: CheckBox
private lateinit var timerDisplay: TextView private var _binding: DialogSleepTimerBinding? = null
private val binding get() = _binding!!
private val shouldFinishLastSong: CheckBox get() = binding.shouldFinishLastSong
private val seekBar: SeekBar get() = binding.seekBar
private val timerDisplay: TextView get() = binding.timerDisplay
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
timerUpdater = TimerUpdater() timerUpdater = TimerUpdater()
val binding = DialogSleepTimerBinding.inflate(layoutInflater) _binding = DialogSleepTimerBinding.inflate(layoutInflater)
shouldFinishLastSong = binding.shouldFinishLastSong
timerDisplay = binding.timerDisplay
val finishMusic = PreferenceUtil.isSleepTimerFinishMusic val finishMusic = PreferenceUtil.isSleepTimerFinishMusic
shouldFinishLastSong.apply { shouldFinishLastSong.apply {
addAccentColor() addAccentColor()
isChecked = finishMusic isChecked = finishMusic
} }
binding.seekBar.apply { seekBar.apply {
addAccentColor() addAccentColor()
seekArcProgress = PreferenceUtil.lastSleepTimerValue seekArcProgress = PreferenceUtil.lastSleepTimerValue
updateTimeDisplayTime() updateTimeDisplayTime()
@ -85,47 +88,65 @@ class SleepTimerDialog : DialogFragment() {
PreferenceUtil.lastSleepTimerValue = seekArcProgress PreferenceUtil.lastSleepTimerValue = seekArcProgress
} }
}) })
return materialDialog(R.string.action_sleep_timer)
.setView(binding.root)
.setPositiveButton(R.string.action_set) { _, _ ->
PreferenceUtil.isSleepTimerFinishMusic = shouldFinishLastSong.isChecked
val minutes = seekArcProgress
val pi = makeTimerPendingIntent(PendingIntent.FLAG_CANCEL_CURRENT)
val nextSleepTimerElapsedTime = SystemClock.elapsedRealtime() + minutes * 60 * 1000
PreferenceUtil.nextSleepTimerElapsedRealTime = nextSleepTimerElapsedTime.toInt()
val am = requireContext().getSystemService<AlarmManager>()
am?.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextSleepTimerElapsedTime, pi)
Toast.makeText( materialDialog(R.string.action_sleep_timer).apply {
requireContext(), if (PreferenceUtil.nextSleepTimerElapsedRealTime > System.currentTimeMillis()) {
requireContext().resources.getString(R.string.sleep_timer_set, minutes), seekBar.isVisible = false
Toast.LENGTH_SHORT shouldFinishLastSong.isVisible = false
).show() timerUpdater.start()
} setPositiveButton(android.R.string.ok, null)
.setNegativeButton(android.R.string.cancel) { _, _ -> setNegativeButton(R.string.cast_stop) { _, _ ->
val previous = makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) timerUpdater.cancel()
if (previous != null) { val previous = makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE)
val am = requireContext().getSystemService<AlarmManager>() if (previous != null) {
am?.cancel(previous) val am = requireContext().getSystemService<AlarmManager>()
previous.cancel() am?.cancel(previous)
Toast.makeText( previous.cancel()
requireContext(),
requireContext().resources.getString(R.string.sleep_timer_canceled),
Toast.LENGTH_SHORT
).show()
val musicService = MusicPlayerRemote.musicService
if (musicService != null && musicService.pendingQuit) {
musicService.pendingQuit = false
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
requireContext().resources.getString(R.string.sleep_timer_canceled), requireContext().resources.getString(R.string.sleep_timer_canceled),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
val musicService = MusicPlayerRemote.musicService
if (musicService != null && musicService.pendingQuit) {
musicService.pendingQuit = false
Toast.makeText(
requireContext(),
requireContext().resources.getString(R.string.sleep_timer_canceled),
Toast.LENGTH_SHORT
).show()
}
} }
} }
} else {
seekBar.isVisible = true
shouldFinishLastSong.isVisible = true
setPositiveButton(R.string.action_set) { _, _ ->
PreferenceUtil.isSleepTimerFinishMusic = shouldFinishLastSong.isChecked
val minutes = seekArcProgress
val pi = makeTimerPendingIntent(PendingIntent.FLAG_CANCEL_CURRENT)
val nextSleepTimerElapsedTime =
SystemClock.elapsedRealtime() + minutes * 60 * 1000
PreferenceUtil.nextSleepTimerElapsedRealTime = nextSleepTimerElapsedTime.toInt()
val am = requireContext().getSystemService<AlarmManager>()
am?.setExact(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
nextSleepTimerElapsedTime,
pi
)
Toast.makeText(
requireContext(),
requireContext().resources.getString(R.string.sleep_timer_set, minutes),
Toast.LENGTH_SHORT
).show()
}
} }
.create() setView(binding.root)
.colorButtons() dialog = create()
}
return dialog
} }
private fun updateTimeDisplayTime() { private fun updateTimeDisplayTime() {
@ -147,14 +168,10 @@ class SleepTimerDialog : DialogFragment() {
} else intent.setAction(ACTION_QUIT) } else intent.setAction(ACTION_QUIT)
} }
private fun updateCancelButton() { override fun onDismiss(dialog: DialogInterface) {
val musicService = MusicPlayerRemote.musicService super.onDismiss(dialog)
if (musicService != null && musicService.pendingQuit) { timerUpdater.cancel()
dialog.getActionButton(WhichButton.NEUTRAL).text = _binding = null
dialog.context.getString(R.string.cancel_current_timer)
} else {
dialog.getActionButton(WhichButton.NEUTRAL).text = null
}
} }
private inner class TimerUpdater : private inner class TimerUpdater :
@ -164,10 +181,9 @@ class SleepTimerDialog : DialogFragment() {
) { ) {
override fun onTick(millisUntilFinished: Long) { override fun onTick(millisUntilFinished: Long) {
timerDisplay.text = MusicUtil.getReadableDurationString(millisUntilFinished)
} }
override fun onFinish() { override fun onFinish() {}
updateCancelButton()
}
} }
} }

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

@ -135,7 +135,9 @@ fun Button.accentTextColor() {
fun MaterialButton.accentBackgroundColor() { fun MaterialButton.accentBackgroundColor() {
if (materialYou) return if (materialYou) return
backgroundTintList = ColorStateList.valueOf(context.accentColor()) backgroundTintList = ColorStateList(
arrayOf(intArrayOf(android.R.attr.state_enabled), intArrayOf()),
intArrayOf(context.accentColor(), context.accentColor().addAlpha(0.12f)))
} }
fun MaterialButton.accentOutlineColor() { fun MaterialButton.accentOutlineColor() {
@ -163,6 +165,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 +312,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

@ -21,6 +21,7 @@ import androidx.navigation.NavController
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.navOptions
fun Fragment.navigate(@IdRes id: Int) = findNavController().navigate(id) fun Fragment.navigate(@IdRes id: Int) = findNavController().navigate(id)
@ -37,3 +38,13 @@ fun AppCompatActivity.findNavController(@IdRes id: Int): NavController {
val fragment = supportFragmentManager.findFragmentById(id) as NavHostFragment val fragment = supportFragmentManager.findFragmentById(id) as NavHostFragment
return fragment.navController return fragment.navController
} }
val fadeNavOptions
get() = navOptions {
anim {
enter = android.R.anim.fade_in
exit = android.R.anim.fade_out
popEnter = android.R.anim.fade_in
popExit = android.R.anim.fade_out
}
}

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

@ -38,8 +38,12 @@ import code.name.monkey.retromusic.util.RetroUtil
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.navigation.NavigationBarView
import com.google.android.material.navigationrail.NavigationRailView
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
@ -72,7 +76,8 @@ fun EditText.appHandleColor(): EditText {
* Instead, take a snapshot of the view, and animate this in, only changing the visibility (and * Instead, take a snapshot of the view, and animate this in, only changing the visibility (and
* thus layout) when the animation completes. * thus layout) when the animation completes.
*/ */
fun BottomNavigationView.show() { fun NavigationBarView.show() {
if (this is NavigationRailView) return
if (isVisible) return if (isVisible) return
val parent = parent as ViewGroup val parent = parent as ViewGroup
@ -90,10 +95,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
@ -116,7 +121,8 @@ fun BottomNavigationView.show() {
* Instead, take a snapshot, instantly hide the view (so content lays out to fill), then animate * Instead, take a snapshot, instantly hide the view (so content lays out to fill), then animate
* out the snapshot. * out the snapshot.
*/ */
fun BottomNavigationView.hide() { fun NavigationBarView.hide() {
if (this is NavigationRailView) return
if (isGone) return if (isGone) return
if (!isLaidOut) { if (!isLaidOut) {
@ -130,10 +136,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 +170,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 +266,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 +307,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

@ -1,13 +1,14 @@
package code.name.monkey.retromusic.fragments package code.name.monkey.retromusic.fragments
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.view.GestureDetector
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewConfiguration
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlin.math.abs
/** /**
* @param activity, Activity * @param activity, Activity
@ -16,46 +17,63 @@ import kotlinx.coroutines.*
class MusicSeekSkipTouchListener(val activity: FragmentActivity, val next: Boolean) : class MusicSeekSkipTouchListener(val activity: FragmentActivity, val next: Boolean) :
View.OnTouchListener { View.OnTouchListener {
var job: Job? = null private var job: Job? = null
var counter = 0 private var counter = 0
var wasSeeking = false private var wasSeeking = false
private val gestureDetector = GestureDetector(activity, object : private var startX = 0f
GestureDetector.SimpleOnGestureListener() { private var startY = 0f
override fun onDown(e: MotionEvent?): Boolean {
job = activity.lifecycleScope.launch(Dispatchers.Default) { private val scaledTouchSlop = ViewConfiguration.get(activity).scaledTouchSlop
counter = 0
while (isActive) {
delay(500)
wasSeeking = true
var seekingDuration = MusicPlayerRemote.songProgressMillis
if (next) {
seekingDuration += 5000 * (counter.floorDiv(2) + 1)
} else {
seekingDuration -= 5000 * (counter.floorDiv(2) + 1)
}
MusicPlayerRemote.seekTo(seekingDuration)
counter += 1
}
}
return super.onDown(e)
}
})
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, event: MotionEvent?): Boolean { override fun onTouch(v: View?, event: MotionEvent?): Boolean {
val action = event?.actionMasked when (event?.actionMasked) {
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { MotionEvent.ACTION_DOWN -> {
job?.cancel() startX = event.x
if (!wasSeeking) { startY = event.y
if (next) { job = activity.lifecycleScope.launch(Dispatchers.Default) {
MusicPlayerRemote.playNextSong() counter = 0
} else { while (isActive) {
MusicPlayerRemote.back() delay(500)
wasSeeking = true
var seekingDuration = MusicPlayerRemote.songProgressMillis
if (next) {
seekingDuration += 5000 * (counter.floorDiv(2) + 1)
} else {
seekingDuration -= 5000 * (counter.floorDiv(2) + 1)
}
withContext(Dispatchers.Main) {
MusicPlayerRemote.seekTo(seekingDuration)
}
counter += 1
}
} }
} }
wasSeeking = false MotionEvent.ACTION_UP -> {
job?.cancel()
val endX = event.x
val endY = event.y
if (!wasSeeking && isAClick(startX, endX, startY, endY)) {
if (next) {
MusicPlayerRemote.playNextSong()
} else {
MusicPlayerRemote.back()
}
}
wasSeeking = false
}
MotionEvent.ACTION_CANCEL -> {
job?.cancel()
}
} }
return gestureDetector.onTouchEvent(event) return false
}
private fun isAClick(startX: Float, endX: Float, startY: Float, endY: Float): Boolean {
val differenceX = abs(startX - endX)
val differenceY = abs(startY - endY)
return !(differenceX > scaledTouchSlop || differenceY > scaledTouchSlop)
} }
} }

View file

@ -46,7 +46,7 @@ class AboutFragment : Fragment(R.layout.fragment_about), View.OnClickListener {
binding.aboutContent.root.applyInsetter { binding.aboutContent.root.applyInsetter {
type(navigationBars = true) { type(navigationBars = true) {
padding() padding(vertical = true)
} }
} }
} }

View file

@ -31,6 +31,7 @@ import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.transition.Fade
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.EXTRA_ALBUM_ID import code.name.monkey.retromusic.EXTRA_ALBUM_ID
@ -62,10 +63,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
@ -112,6 +110,8 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
_binding = FragmentAlbumDetailsBinding.bind(view) _binding = FragmentAlbumDetailsBinding.bind(view)
enterTransition = Fade()
exitTransition = Fade()
mainActivity.addMusicServiceEventListener(detailsViewModel) mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(binding.toolbar) mainActivity.setSupportActionBar(binding.toolbar)
@ -245,10 +245,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

@ -22,6 +22,7 @@ import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.transition.Fade
import code.name.monkey.retromusic.EXTRA_ALBUM_ID import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
@ -85,6 +86,8 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
_binding = FragmentArtistDetailsBinding.bind(view) _binding = FragmentArtistDetailsBinding.bind(view)
enterTransition = Fade()
exitTransition = Fade()
mainActivity.addMusicServiceEventListener(detailsViewModel) mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(binding.toolbar) mainActivity.setSupportActionBar(binding.toolbar)
binding.toolbar.title = null binding.toolbar.title = null
@ -180,8 +183,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 -> {
@ -159,4 +154,9 @@ class BackupFragment : Fragment(R.layout.fragment_backup), BackupAdapter.BackupC
} }
return false return false
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
} }

View file

@ -33,7 +33,7 @@ abstract class AbsMainActivityFragment(@LayoutRes layout: Int) : AbsMusicService
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val menuHost: MenuHost = requireActivity() val menuHost: MenuHost = requireActivity() as MenuHost
menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.STARTED) menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.STARTED)
} }
} }

View file

@ -17,12 +17,14 @@ package code.name.monkey.retromusic.fragments.base
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.annotation.CallSuper
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.navOptions 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.
@ -60,11 +62,14 @@ open class AbsMusicServiceFragment(@LayoutRes layout: Int) : Fragment(layout),
serviceActivity = null serviceActivity = null
} }
@CallSuper
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()
} }
@CallSuper
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
serviceActivity?.removeMusicServiceEventListener(this) serviceActivity?.removeMusicServiceEventListener(this)

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,45 +79,76 @@ 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()
if (isSeeking) {
progressSlider?.progress = progress
} else { } else {
progressAnimator = ObjectAnimator.ofInt(progressSlider, "progress", progress).apply { seekBar?.max = total
duration = SLIDER_ANIMATION_TIME
interpolator = LinearInterpolator()
start()
}
if (isSeeking) {
seekBar?.progress = progress
} else {
progressAnimator =
ObjectAnimator.ofInt(seekBar, "progress", progress).apply {
duration = SLIDER_ANIMATION_TIME
interpolator = LinearInterpolator()
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)
if (fromUser) { })
onUpdateProgressViews( progressSlider?.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
progress, override fun onStartTrackingTouch(slider: Slider) {
MusicPlayerRemote.songDurationMillis onStartTrackingTouch()
)
}
} }
override fun onStartTrackingTouch(seekBar: SeekBar) { override fun onStopTrackingTouch(slider: Slider) {
isSeeking = true onStopTrackingTouch(slider.value.toInt())
progressViewUpdateHelper.stop()
progressAnimator?.cancel()
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
isSeeking = false
MusicPlayerRemote.seekTo(seekBar.progress)
progressViewUpdateHelper.start()
} }
}) })
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) {
onUpdateProgressViews(value, MusicPlayerRemote.songDurationMillis)
}
}
private fun onStartTrackingTouch() {
isSeeking = true
progressViewUpdateHelper.stop()
progressAnimator?.cancel()
}
private fun onStopTrackingTouch(value: Int) {
isSeeking = false
MusicPlayerRemote.seekTo(value)
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(),
@ -381,9 +400,7 @@ fun goToArtist(activity: Activity) {
findNavController(R.id.fragment_container).navigate( findNavController(R.id.fragment_container).navigate(
R.id.artistDetailsFragment, R.id.artistDetailsFragment,
bundleOf(EXTRA_ARTIST_ID to song.artistId), bundleOf(EXTRA_ARTIST_ID to song.artistId)
null,
null
) )
} }
} }
@ -402,9 +419,7 @@ fun goToAlbum(activity: Activity) {
findNavController(R.id.fragment_container).navigate( findNavController(R.id.fragment_container).navigate(
R.id.albumDetailsFragment, R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to song.albumId), bundleOf(EXTRA_ALBUM_ID to song.albumId)
null,
null
) )
} }
} }
@ -421,8 +436,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

@ -32,7 +32,6 @@ import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.dip import code.name.monkey.retromusic.extensions.dip
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.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ThemedFastScroller.create import code.name.monkey.retromusic.util.ThemedFastScroller.create
@ -61,6 +60,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
mainActivity.supportActionBar?.title = null mainActivity.supportActionBar?.title = null
initLayoutManager() initLayoutManager()
initAdapter() initAdapter()
checkForMargins()
setUpRecyclerView() setUpRecyclerView()
setupToolbar() setupToolbar()
binding.shuffleButton.fitsSystemWindows = PreferenceUtil.isFullScreenMode binding.shuffleButton.fitsSystemWindows = PreferenceUtil.isFullScreenMode
@ -118,7 +118,6 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
adapter = this@AbsRecyclerViewFragment.adapter adapter = this@AbsRecyclerViewFragment.adapter
create(this) create(this)
} }
checkForPadding()
} }
protected open fun createFastScroller(recyclerView: RecyclerView): FastScroller { protected open fun createFastScroller(recyclerView: RecyclerView): FastScroller {
@ -131,7 +130,6 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
checkIsEmpty() checkIsEmpty()
checkForPadding()
} }
}) })
} }
@ -148,16 +146,12 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
binding.empty.isVisible = adapter!!.itemCount == 0 binding.empty.isVisible = adapter!!.itemCount == 0
} }
private fun checkForPadding() { private fun checkForMargins() {
val itemCount: Int = adapter?.itemCount ?: 0 if (mainActivity.isBottomNavVisible) {
binding.recyclerView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
binding.recyclerView.updatePadding( bottomMargin = dip(R.dimen.bottom_nav_height)
bottom = if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
dip(R.dimen.mini_player_height_expanded)
} else {
dip(R.dimen.bottom_nav_height)
} }
) }
} }
private fun initLayoutManager() { private fun initLayoutManager() {
@ -169,16 +163,6 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
@NonNull @NonNull
protected abstract fun createAdapter(): A protected abstract fun createAdapter(): A
override fun onQueueChanged() {
super.onQueueChanged()
checkForPadding()
}
override fun onServiceConnected() {
super.onServiceConnected()
checkForPadding()
}
protected fun invalidateLayoutManager() { protected fun invalidateLayoutManager() {
initLayoutManager() initLayoutManager()
binding.recyclerView.layoutManager = layoutManager binding.recyclerView.layoutManager = layoutManager
@ -216,7 +200,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
) )
@ -232,6 +216,11 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
return false return false
} }
override fun onResume() {
super.onResume()
checkForMargins()
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View file

@ -17,15 +17,14 @@ import android.content.Context
import android.media.MediaScannerConnection import android.media.MediaScannerConnection
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.view.Menu import android.view.*
import android.view.MenuInflater
import android.view.MenuItem
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.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.loader.app.LoaderManager import androidx.loader.app.LoaderManager
import androidx.loader.content.Loader import androidx.loader.content.Loader
@ -44,7 +43,6 @@ import code.name.monkey.retromusic.databinding.FragmentFolderBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote.openQueue import code.name.monkey.retromusic.helper.MusicPlayerRemote.openQueue
import code.name.monkey.retromusic.helper.MusicPlayerRemote.playingQueue
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.ICabCallback import code.name.monkey.retromusic.interfaces.ICabCallback
import code.name.monkey.retromusic.interfaces.ICabHolder import code.name.monkey.retromusic.interfaces.ICabHolder
@ -66,7 +64,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 +80,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
@ -98,14 +98,16 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
private var storageItems = ArrayList<Storage>() private var storageItems = ArrayList<Storage>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_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()
setUpBreadCrumbs() setUpBreadCrumbs()
checkForMargins()
setUpRecyclerView() setUpRecyclerView()
setUpAdapter() setUpAdapter()
setUpTitle() setUpTitle()
@ -119,16 +121,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 +184,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 +225,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 +263,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 +331,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 +345,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 +373,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
) )
@ -384,14 +383,9 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
return false return false
} }
override fun onQueueChanged() { override fun onResume() {
super.onQueueChanged() super.onResume()
checkForPadding() checkForMargins()
}
override fun onServiceConnected() {
super.onServiceConnected()
checkForPadding()
} }
override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab { override fun openCab(menuRes: Int, callback: ICabCallback): AttachedCab {
@ -412,13 +406,11 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
return cab as AttachedCab return cab as AttachedCab
} }
private fun checkForPadding() { private fun checkForMargins() {
val count = adapter?.itemCount ?: 0 if (mainActivity.isBottomNavVisible) {
if (_binding != null) { binding.recyclerView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
binding.recyclerView.updatePadding( bottomMargin = dip(R.dimen.bottom_nav_height)
bottom = if (count > 0 && playingQueue.isNotEmpty()) dip(R.dimen.mini_player_height_expanded) }
else dip(R.dimen.mini_player_height)
)
} }
} }
@ -501,12 +493,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
@ -524,7 +510,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
private suspend fun listPaths( private suspend fun listPaths(
file: File, file: File,
fileFilter: FileFilter, fileFilter: FileFilter,
doOnPathListed: (paths: Array<String?>) -> Unit doOnPathListed: (paths: Array<String?>) -> Unit,
) { ) {
val paths = try { val paths = try {
val paths: Array<String?> val paths: Array<String?>
@ -578,10 +564,10 @@ 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,
) { ) {
val songs = try { val songs = try {
val fileList = FileUtil.listFilesDeep(files, fileFilter) val fileList = FileUtil.listFilesDeep(files, fileFilter)
@ -613,7 +599,6 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
checkIsEmpty() checkIsEmpty()
checkForPadding()
} }
}) })
binding.recyclerView.adapter = adapter binding.recyclerView.adapter = adapter

View file

@ -76,6 +76,7 @@ GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(),
} }
override val titleRes: Int override val titleRes: Int
get() = R.string.genres get() = R.string.genres
@ -100,9 +101,7 @@ GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(),
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
findNavController().navigate( findNavController().navigate(
R.id.genreDetailsFragment, R.id.genreDetailsFragment,
bundleOf(EXTRA_GENRE to genre), bundleOf(EXTRA_GENRE to genre)
null,
null
) )
} }
} }

View file

@ -15,17 +15,15 @@
package code.name.monkey.retromusic.fragments.home package code.name.monkey.retromusic.fragments.home
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.*
import android.view.MenuInflater
import android.view.MenuItem
import android.view.MenuItem.SHOW_AS_ACTION_IF_ROOM import android.view.MenuItem.SHOW_AS_ACTION_IF_ROOM
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.text.parseAsHtml import androidx.core.text.parseAsHtml
import androidx.core.view.doOnLayout import androidx.core.view.doOnLayout
import androidx.core.view.doOnPreDraw import androidx.core.view.doOnPreDraw
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -38,6 +36,7 @@ import code.name.monkey.retromusic.databinding.FragmentHomeBinding
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.dip
import code.name.monkey.retromusic.extensions.drawNextToNavbar import code.name.monkey.retromusic.extensions.drawNextToNavbar
import code.name.monkey.retromusic.extensions.elevatedAccentColor import code.name.monkey.retromusic.extensions.elevatedAccentColor
import code.name.monkey.retromusic.fragments.ReloadType import code.name.monkey.retromusic.fragments.ReloadType
@ -47,6 +46,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
@ -71,6 +71,8 @@ class HomeFragment :
enterTransition = MaterialFadeThrough().addTarget(binding.contentContainer) enterTransition = MaterialFadeThrough().addTarget(binding.contentContainer)
reenterTransition = MaterialFadeThrough().addTarget(binding.contentContainer) reenterTransition = MaterialFadeThrough().addTarget(binding.contentContainer)
checkForMargins()
val homeAdapter = HomeAdapter(mainActivity) val homeAdapter = HomeAdapter(mainActivity)
binding.recyclerView.apply { binding.recyclerView.apply {
layoutManager = LinearLayoutManager(mainActivity) layoutManager = LinearLayoutManager(mainActivity)
@ -189,6 +191,14 @@ class HomeFragment :
binding.actionShuffle.elevatedAccentColor() binding.actionShuffle.elevatedAccentColor()
} }
private fun checkForMargins() {
if (mainActivity.isBottomNavVisible) {
binding.recyclerView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = dip(R.dimen.bottom_nav_height)
}
}
}
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_main, menu) inflater.inflate(R.menu.menu_main, menu)
menu.removeItem(R.id.action_grid_size) menu.removeItem(R.id.action_grid_size)
@ -211,17 +221,19 @@ class HomeFragment :
} }
fun setSharedAxisXTransitions() { fun setSharedAxisXTransitions() {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true).addTarget(CoordinatorLayout::class.java) exitTransition =
MaterialSharedAxis(MaterialSharedAxis.X, true).addTarget(CoordinatorLayout::class.java)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
} }
private fun setSharedAxisYTransitions() { private fun setSharedAxisYTransitions() {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Y, true).addTarget(CoordinatorLayout::class.java) exitTransition =
MaterialSharedAxis(MaterialSharedAxis.Y, true).addTarget(CoordinatorLayout::class.java)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false) reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
} }
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 +289,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
) )
@ -300,7 +312,9 @@ class HomeFragment :
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
checkForMargins()
libraryViewModel.forceReload(ReloadType.HomeSections) libraryViewModel.forceReload(ReloadType.HomeSections)
exitTransition = null
} }
override fun onDestroyView() { override fun onDestroyView() {

View file

@ -80,7 +80,7 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
navGraph.setStartDestination(categoryInfo.category.id) navGraph.setStartDestination(categoryInfo.category.id)
} }
navController.graph = navGraph navController.graph = navGraph
NavigationUI.setupWithNavController(mainActivity.bottomNavigationView, navController) NavigationUI.setupWithNavController(mainActivity.navigationView, navController)
navController.addOnDestinationChangedListener { _, _, _ -> navController.addOnDestinationChangedListener { _, _, _ ->
binding.appBarLayout.setExpanded(true, true) binding.appBarLayout.setExpanded(true, true)
} }
@ -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

@ -29,7 +29,6 @@ import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.album.AlbumAdapter import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
@ -37,7 +36,6 @@ import code.name.monkey.retromusic.adapter.song.ShuffleButtonSongAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding
import code.name.monkey.retromusic.db.toSong import code.name.monkey.retromusic.db.toSong
import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.extensions.surfaceColor import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.interfaces.IAlbumClickListener import code.name.monkey.retromusic.interfaces.IAlbumClickListener
@ -71,7 +69,8 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
RECENT_ARTISTS, RECENT_ARTISTS,
TOP_ALBUMS, TOP_ALBUMS,
RECENT_ALBUMS, RECENT_ALBUMS,
FAVOURITES -> { FAVOURITES,
-> {
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
} }
@ -103,13 +102,6 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
TOP_PLAYED_PLAYLIST -> topPlayed() TOP_PLAYED_PLAYLIST -> topPlayed()
} }
binding.recyclerView.adapter?.registerAdapterDataObserver(object : AdapterDataObserver() {
override fun onChanged() {
super.onChanged()
val height = dipToPix(52f)
binding.recyclerView.updatePadding(bottom = height.toInt())
}
})
binding.appBarLayout.statusBarForeground = binding.appBarLayout.statusBarForeground =
MaterialShapeDrawable.createWithElevationOverlay(requireContext()) MaterialShapeDrawable.createWithElevationOverlay(requireContext())
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
@ -282,7 +274,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

@ -125,9 +125,9 @@ class LyricsFragment : AbsMainActivityFragment(R.layout.fragment_lyrics) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
updateTitleSong()
enterTransition = Fade() enterTransition = Fade()
exitTransition = Fade() exitTransition = Fade()
updateTitleSong()
lyricsSectionsAdapter = LyricsSectionsAdapter(requireActivity()) lyricsSectionsAdapter = LyricsSectionsAdapter(requireActivity())
_binding = FragmentLyricsBinding.bind(view) _binding = FragmentLyricsBinding.bind(view)
binding.container.transitionName = "lyrics" binding.container.transitionName = "lyrics"
@ -425,11 +425,17 @@ class LyricsFragment : AbsMainActivityFragment(R.layout.fragment_lyrics) {
super.onPause() super.onPause()
updateHelper.stop() updateHelper.stop()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
} }
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
if (MusicPlayerRemote.playingQueue.isNotEmpty()) if (MusicPlayerRemote.playingQueue.isNotEmpty())
(requireActivity() as MainActivity).expandPanel() (requireActivity() as MainActivity).expandPanel()
_binding = null
} }
} }

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,29 +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")
if (viewPager.currentItem != MusicPlayerRemote.position) {
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 -> {
maybeInitLyrics() if (PreferenceUtil.showLyrics) {
} else { maybeInitLyrics()
showLyrics(false) } else {
progressViewUpdateHelper?.stop() showLyrics(false)
progressViewUpdateHelper?.stop()
}
}
LYRICS_TYPE -> {
maybeInitLyrics()
} }
} else if (key == LYRICS_TYPE) {
maybeInitLyrics()
} }
} }
@ -244,15 +257,15 @@ 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)
} }
} }
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
}
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
logD("Page Selected $position")
currentPosition = position currentPosition = position
if (binding.viewPager.adapter != null) { if (binding.viewPager.adapter != null) {
(binding.viewPager.adapter as AlbumCoverPagerAdapter).receiveColor( (binding.viewPager.adapter as AlbumCoverPagerAdapter).receiveColor(

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

@ -139,9 +139,13 @@ class BlurPlayerFragment : AbsPlayerFragment(R.layout.fragment_blur),
updateBlur() updateBlur()
} }
override fun onPause() {
super.onPause()
lastRequest = null
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
lastRequest = null
PreferenceManager.getDefaultSharedPreferences(requireContext()) PreferenceManager.getDefaultSharedPreferences(requireContext())
.registerOnSharedPreferenceChangeListener(this) .registerOnSharedPreferenceChangeListener(this)
} }

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

@ -152,6 +152,11 @@ class CardBlurFragment : AbsPlayerFragment(R.layout.fragment_card_blur_player),
} }
} }
override fun onPause() {
super.onPause()
lastRequest = null
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
lastRequest = null lastRequest = null

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())
@ -166,7 +162,6 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
lastRequest = null
progressViewUpdateHelper.start() progressViewUpdateHelper.start()
if (audioVolumeObserver == null) { if (audioVolumeObserver == null) {
audioVolumeObserver = AudioVolumeObserver(requireActivity()) audioVolumeObserver = AudioVolumeObserver(requireActivity())
@ -183,6 +178,7 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
lastRequest = null
progressViewUpdateHelper.stop() progressViewUpdateHelper.stop()
} }
@ -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( value.toInt(),
MusicPlayerRemote.songProgressMillis, 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

@ -85,7 +85,7 @@ class ClassicPlayerFragment : AbsPlayerFragment(R.layout.fragment_classic_player
private val bottomSheetCallbackList = object : BottomSheetBehavior.BottomSheetCallback() { private val bottomSheetCallbackList = object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) { override fun onSlide(bottomSheet: View, slideOffset: Float) {
mainActivity.getBottomSheetBehavior().isDraggable = false mainActivity.getBottomSheetBehavior().isDraggable = false
binding.playerQueueSheet.setContentPadding( binding.playerQueueSheet.setContentPadding(
binding.playerQueueSheet.contentPaddingLeft, binding.playerQueueSheet.contentPaddingLeft,
(slideOffset * binding.statusBar.height).toInt(), (slideOffset * binding.statusBar.height).toInt(),

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,10 +177,9 @@ 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() {

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) { onUpdateProgressViews(
MusicPlayerRemote.seekTo(progress) value.toInt(),
onUpdateProgressViews( MusicPlayerRemote.songDurationMillis
MusicPlayerRemote.songProgressMillis, )
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

@ -17,10 +17,8 @@ import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter
import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding
import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.toSongs import code.name.monkey.retromusic.db.toSongs
import code.name.monkey.retromusic.extensions.dip
import code.name.monkey.retromusic.extensions.surfaceColor import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
import code.name.monkey.retromusic.interfaces.ICabCallback import code.name.monkey.retromusic.interfaces.ICabCallback
import code.name.monkey.retromusic.interfaces.ICabHolder import code.name.monkey.retromusic.interfaces.ICabHolder
@ -129,17 +127,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
return PlaylistMenuHelper.handleMenuClick(requireActivity(), playlist, item) return PlaylistMenuHelper.handleMenuClick(requireActivity(), playlist, item)
} }
private fun checkForPadding() {
val itemCount: Int = playlistSongAdapter.itemCount
if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
binding.recyclerView.updatePadding(bottom = dip(R.dimen.mini_player_height))
} else {
binding.recyclerView.updatePadding(bottom = 0)
}
}
private fun checkIsEmpty() { private fun checkIsEmpty() {
checkForPadding()
binding.empty.isVisible = playlistSongAdapter.itemCount == 0 binding.empty.isVisible = playlistSongAdapter.itemCount == 0
binding.emptyText.isVisible = playlistSongAdapter.itemCount == 0 binding.emptyText.isVisible = playlistSongAdapter.itemCount == 0
} }
@ -177,7 +165,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

@ -109,7 +109,7 @@ class PlaylistsFragment :
7 -> gridSizeMenu.findItem(R.id.action_grid_size_7).isChecked = true 7 -> gridSizeMenu.findItem(R.id.action_grid_size_7).isChecked = true
8 -> gridSizeMenu.findItem(R.id.action_grid_size_8).isChecked = true 8 -> gridSizeMenu.findItem(R.id.action_grid_size_8).isChecked = true
} }
val gridSize = if (RetroUtil.isLandscape) 4 else 2 val gridSize = if (RetroUtil.isLandscape) 4 else 3
if (gridSize < 8) { if (gridSize < 8) {
gridSizeMenu.findItem(R.id.action_grid_size_8).isVisible = false gridSizeMenu.findItem(R.id.action_grid_size_8).isVisible = false
} }
@ -245,9 +245,7 @@ class PlaylistsFragment :
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
findNavController().navigate( findNavController().navigate(
R.id.playlistDetailsFragment, R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to playlistWithSongs), bundleOf(EXTRA_PLAYLIST to playlistWithSongs)
null,
null
) )
} }
} }

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 {
@ -151,14 +146,20 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search),
} }
} }
private fun checkForMargins() {
if (mainActivity.isBottomNavVisible) {
binding.recyclerView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = dip(R.dimen.bottom_nav_height)
}
}
}
private fun setupRecyclerView() { private fun setupRecyclerView() {
searchAdapter = SearchAdapter(requireActivity(), emptyList()) searchAdapter = SearchAdapter(requireActivity(), emptyList())
searchAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { searchAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
binding.empty.isVisible = searchAdapter.itemCount < 1 binding.empty.isVisible = searchAdapter.itemCount < 1
val height = dipToPix(52f)
binding.recyclerView.updatePadding(bottom = height.toInt())
} }
}) })
binding.recyclerView.apply { binding.recyclerView.apply {
@ -224,6 +225,11 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search),
} }
} }
override fun onResume() {
super.onResume()
checkForMargins()
}
override fun onDestroyView() { override fun onDestroyView() {
hideKeyboard(view) hideKeyboard(view)
super.onDestroyView() super.onDestroyView()

View file

@ -19,13 +19,13 @@ import android.graphics.drawable.ColorDrawable
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.core.view.updatePadding
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceManager 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.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.OnThemeChangedListener import code.name.monkey.retromusic.extensions.dip
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
@ -71,9 +71,10 @@ abstract class AbsSettingsFragment : ATEPreferenceFragmentCompat() {
listView.overScrollMode = View.OVER_SCROLL_NEVER listView.overScrollMode = View.OVER_SCROLL_NEVER
} }
listView.updatePadding(bottom = dip(R.dimen.mini_player_height))
listView.applyInsetter { listView.applyInsetter {
type(navigationBars = true) { type(navigationBars = true) {
padding() padding(vertical = true)
} }
} }
invalidateSettings() invalidateSettings()
@ -106,10 +107,6 @@ abstract class AbsSettingsFragment : ATEPreferenceFragmentCompat() {
} }
fun restartActivity() { fun restartActivity() {
if (activity is OnThemeChangedListener && !VersionUtils.hasS()) { activity?.recreate()
(activity as OnThemeChangedListener).onThemeValuesChanged()
} else {
activity?.recreate()
}
} }
} }

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,37 @@
* 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.fragment.app.Fragment
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.findNavController
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 : Fragment(R.layout.fragment_settings), ColorCallback {
private lateinit var binding: ActivitySettingsBinding private var _binding: FragmentSettingsBinding? = null
override fun onCreate(savedInstanceState: Bundle?) { private val binding get() = _binding!!
val mSavedInstanceState = extra<Bundle>(TAG).value ?: savedInstanceState
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()
} }
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,51 +67,19 @@ 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() activity?.recreate()
} }
override fun onThemeValuesChanged() { override fun onDestroyView() {
restart() super.onDestroyView()
} _binding = null
private fun restart() {
val savedInstanceState = Bundle().apply {
onSaveInstanceState(this)
}
finish()
val intent = Intent(this, this::class.java).putExtra(TAG, savedInstanceState)
startActivity(intent)
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
} }
companion object { companion object {
val TAG: String = SettingsActivity::class.java.simpleName val TAG: String = SettingsFragment::class.java.simpleName
} }
} }
interface OnThemeChangedListener {
fun onThemeValuesChanged()
}

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

@ -142,6 +142,13 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
private fun setUpSortOrderMenu(sortOrderMenu: SubMenu) { private fun setUpSortOrderMenu(sortOrderMenu: SubMenu) {
val currentSortOrder: String? = getSortOrder() val currentSortOrder: String? = getSortOrder()
sortOrderMenu.clear() sortOrderMenu.clear()
sortOrderMenu.add(
0,
R.id.action_song_default_sort_order,
0,
R.string.sort_order_default
).isChecked =
currentSortOrder == SongSortOrder.SONG_DEFAULT
sortOrderMenu.add( sortOrderMenu.add(
0, 0,
R.id.action_song_sort_order_asc, R.id.action_song_sort_order_asc,
@ -270,6 +277,7 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
private fun handleSortOrderMenuItem(item: MenuItem): Boolean { private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
val sortOrder: String = when (item.itemId) { val sortOrder: String = when (item.itemId) {
R.id.action_song_default_sort_order -> SongSortOrder.SONG_DEFAULT
R.id.action_song_sort_order_asc -> SongSortOrder.SONG_A_Z R.id.action_song_sort_order_asc -> SongSortOrder.SONG_A_Z
R.id.action_song_sort_order_desc -> SongSortOrder.SONG_Z_A R.id.action_song_sort_order_desc -> SongSortOrder.SONG_Z_A
R.id.action_song_sort_order_artist -> SongSortOrder.SONG_ARTIST R.id.action_song_sort_order_artist -> SongSortOrder.SONG_ARTIST
@ -363,7 +371,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,25 +55,20 @@ 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 DeezerService.createDefaultOkHttpClient(context)
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.addInterceptor(createLogInterceptor())
.build()
)
init { private var okHttp = OkHttpClient.Builder()
okHttp = .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
OkHttpClient.Builder() .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .build()
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.build()
deezerService = DeezerService.invoke(
DeezerService.createDefaultOkHttpClient(context)
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.addInterceptor(createLogInterceptor())
.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

@ -72,8 +72,10 @@ class SortOrder {
companion object { companion object {
const val SONG_DEFAULT = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
/* Song sort order A-Z */ /* Song sort order A-Z */
const val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER const val SONG_A_Z = MediaStore.Audio.Media.TITLE
/* Song sort order Z-A */ /* Song sort order Z-A */
const val SONG_Z_A = "$SONG_A_Z DESC" const val SONG_Z_A = "$SONG_A_Z DESC"

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();
}
}
} }

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