Merge pull request #1471 from RetroMusicPlayer/dev-alpha
Android 13 API changes
This commit is contained in:
commit
8024700b7d
84 changed files with 540 additions and 606 deletions
|
@ -10,13 +10,13 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk 21
|
||||||
targetSdk 32
|
targetSdk 33
|
||||||
|
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
applicationId namespace
|
applicationId namespace
|
||||||
versionCode 10600
|
versionCode 10602
|
||||||
versionName '6.0.4'
|
versionName '6.1.0'
|
||||||
|
|
||||||
buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"")
|
buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"")
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ dependencies {
|
||||||
|
|
||||||
implementation 'androidx.mediarouter:mediarouter:1.3.1'
|
implementation 'androidx.mediarouter:mediarouter:1.3.1'
|
||||||
//Cast Dependencies
|
//Cast Dependencies
|
||||||
normalImplementation 'com.google.android.gms:play-services-cast-framework:21.2.0'
|
normalImplementation 'com.google.android.gms:play-services-cast-framework:21.3.0'
|
||||||
//WebServer by NanoHttpd
|
//WebServer by NanoHttpd
|
||||||
normalImplementation "org.nanohttpd:nanohttpd:2.3.1"
|
normalImplementation "org.nanohttpd:nanohttpd:2.3.1"
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ dependencies {
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
|
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
|
||||||
|
|
||||||
def room_version = '2.5.0'
|
def room_version = '2.5.1'
|
||||||
implementation "androidx.room:room-runtime:$room_version"
|
implementation "androidx.room:room-runtime:$room_version"
|
||||||
implementation "androidx.room:room-ktx:$room_version"
|
implementation "androidx.room:room-ktx:$room_version"
|
||||||
ksp "androidx.room:room-compiler:$room_version"
|
ksp "androidx.room:room-compiler:$room_version"
|
||||||
|
@ -150,11 +150,11 @@ dependencies {
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
|
||||||
|
|
||||||
def koin_version = '3.3.3'
|
def koin_version = '3.4.0'
|
||||||
implementation "io.insert-koin:koin-core:$koin_version"
|
implementation "io.insert-koin:koin-core:$koin_version"
|
||||||
implementation "io.insert-koin:koin-android:$koin_version"
|
implementation "io.insert-koin:koin-android:$koin_version"
|
||||||
|
|
||||||
def glide_version = '4.15.0'
|
def glide_version = '4.15.1'
|
||||||
implementation "com.github.bumptech.glide:glide:$glide_version"
|
implementation "com.github.bumptech.glide:glide:$glide_version"
|
||||||
ksp "com.github.bumptech.glide:ksp:$glide_version"
|
ksp "com.github.bumptech.glide:ksp:$glide_version"
|
||||||
implementation "com.github.bumptech.glide:okhttp3-integration:$glide_version"
|
implementation "com.github.bumptech.glide:okhttp3-integration:$glide_version"
|
||||||
|
@ -176,5 +176,5 @@ dependencies {
|
||||||
implementation 'com.github.dhaval2404:imagepicker:2.1'
|
implementation 'com.github.dhaval2404:imagepicker:2.1'
|
||||||
implementation 'me.zhanghai.android.fastscroll:library:1.2.0'
|
implementation 'me.zhanghai.android.fastscroll:library:1.2.0'
|
||||||
implementation 'cat.ereza:customactivityoncrash:2.4.0'
|
implementation 'cat.ereza:customactivityoncrash:2.4.0'
|
||||||
implementation 'me.tankery.lib:circularSeekBar:1.4.1'
|
implementation 'me.tankery.lib:circularSeekBar:1.4.2'
|
||||||
}
|
}
|
|
@ -8,8 +8,8 @@ import androidx.fragment.app.FragmentActivity
|
||||||
|
|
||||||
fun Context.setUpMediaRouteButton(menu: Menu) {}
|
fun Context.setUpMediaRouteButton(menu: Menu) {}
|
||||||
|
|
||||||
fun FragmentActivity.installLanguageAndRecreate(code: String) {
|
fun FragmentActivity.installLanguageAndRecreate(code: String, onInstallComplete: () -> Unit) {
|
||||||
recreate()
|
onInstallComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.goToProVersion() {}
|
fun Context.goToProVersion() {}
|
||||||
|
|
|
@ -9,7 +9,11 @@
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission
|
||||||
|
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="29" />
|
android:maxSdkVersion="29" />
|
||||||
|
@ -30,16 +34,19 @@
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="@bool/allowBackup"
|
android:allowBackup="@bool/allowBackup"
|
||||||
|
android:appCategory="audio"
|
||||||
android:configChanges="locale|layoutDirection"
|
android:configChanges="locale|layoutDirection"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:localeConfig="@xml/locales_config"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:restoreAnyVersion="true"
|
android:restoreAnyVersion="true"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
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:targetApi="m">
|
tools:ignore="UnusedAttribute">
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.MainActivity"
|
android:name=".activities.MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -296,7 +303,6 @@
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.MusicService"
|
android:name=".service.MusicService"
|
||||||
android:enabled="true"
|
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:foregroundServiceType="mediaPlayback"
|
android:foregroundServiceType="mediaPlayback"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
|
@ -323,6 +329,16 @@
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.gms.car.notification.SmallIcon"
|
android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||||
android:resource="@drawable/ic_notification" />
|
android:resource="@drawable/ic_notification" />
|
||||||
|
|
||||||
|
<!-- For auto-storage of locale on Android 12 and lower -->
|
||||||
|
<service
|
||||||
|
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||||
|
android:enabled="false"
|
||||||
|
android:exported="false">
|
||||||
|
<meta-data
|
||||||
|
android:name="autoStoreLocales"
|
||||||
|
android:value="true" />
|
||||||
|
</service>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -71,6 +71,19 @@
|
||||||
The app heavily relies on Kotlin.
|
The app heavily relies on Kotlin.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5>March 30, 2023</h5>
|
||||||
|
<h2>v6.1.0</h2>
|
||||||
|
<h3>What's New</h3>
|
||||||
|
<ul>
|
||||||
|
<li>App now targets Android 13, support for Granular media permissions, Photo picker, Per-app language preferences & Predictive back gesture</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Fixed</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Fixed playlist reordering crash</li>
|
||||||
|
<li>Other minor bugs fixes and improvements</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h5>March 13, 2023</h5>
|
<h5>March 13, 2023</h5>
|
||||||
<h2>v6.0.4</h2>
|
<h2>v6.0.4</h2>
|
||||||
|
|
|
@ -96,6 +96,7 @@ const val ALBUM_COVER_STYLE = "album_cover_style_id"
|
||||||
const val ALBUM_COVER_TRANSFORM = "album_cover_transform"
|
const val ALBUM_COVER_TRANSFORM = "album_cover_transform"
|
||||||
const val TAB_TEXT_MODE = "tab_text_mode"
|
const val TAB_TEXT_MODE = "tab_text_mode"
|
||||||
const val LANGUAGE_NAME = "language_name"
|
const val LANGUAGE_NAME = "language_name"
|
||||||
|
const val LOCALE_AUTO_STORE_ENABLED = "locale_auto_store_enabled"
|
||||||
const val SLEEP_TIMER_FINISH_SONG = "sleep_timer_finish_song"
|
const val SLEEP_TIMER_FINISH_SONG = "sleep_timer_finish_song"
|
||||||
const val ALBUM_GRID_STYLE = "album_grid_style_home"
|
const val ALBUM_GRID_STYLE = "album_grid_style_home"
|
||||||
const val ARTIST_GRID_STYLE = "artist_grid_style_home"
|
const val ARTIST_GRID_STYLE = "artist_grid_style_home"
|
||||||
|
@ -119,7 +120,6 @@ const val ARTIST_GRID_SIZE_LAND = "artist_grid_size_land"
|
||||||
const val PLAYLIST_GRID_SIZE = "playlist_grid_size"
|
const val PLAYLIST_GRID_SIZE = "playlist_grid_size"
|
||||||
const val PLAYLIST_GRID_SIZE_LAND = "playlist_grid_size_land"
|
const val PLAYLIST_GRID_SIZE_LAND = "playlist_grid_size_land"
|
||||||
const val COLORED_APP_SHORTCUTS = "colored_app_shortcuts"
|
const val COLORED_APP_SHORTCUTS = "colored_app_shortcuts"
|
||||||
const val AUDIO_DUCKING = "audio_ducking"
|
|
||||||
const val LAST_ADDED_CUTOFF = "last_added_interval"
|
const val LAST_ADDED_CUTOFF = "last_added_interval"
|
||||||
const val LAST_SLEEP_TIMER_VALUE = "last_sleep_timer_value"
|
const val LAST_SLEEP_TIMER_VALUE = "last_sleep_timer_value"
|
||||||
const val NEXT_SLEEP_TIMER_ELAPSED_REALTIME = "next_sleep_timer_elapsed_real_time"
|
const val NEXT_SLEEP_TIMER_ELAPSED_REALTIME = "next_sleep_timer_elapsed_real_time"
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package code.name.monkey.retromusic
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.ContextWrapper
|
|
||||||
import android.os.LocaleList
|
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils.hasNougat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class LanguageContextWrapper(base: Context?) : ContextWrapper(base) {
|
|
||||||
companion object {
|
|
||||||
fun wrap(context: Context?, newLocale: Locale?): LanguageContextWrapper {
|
|
||||||
if (context == null) return LanguageContextWrapper(context)
|
|
||||||
val configuration = context.resources.configuration
|
|
||||||
if (hasNougat()) {
|
|
||||||
configuration.setLocale(newLocale)
|
|
||||||
val localeList = LocaleList(newLocale)
|
|
||||||
LocaleList.setDefault(localeList)
|
|
||||||
configuration.setLocales(localeList)
|
|
||||||
} else {
|
|
||||||
configuration.setLocale(newLocale)
|
|
||||||
}
|
|
||||||
return LanguageContextWrapper(context.createConfigurationContext(configuration))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ import androidx.room.Room
|
||||||
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.MIGRATION_23_24
|
import code.name.monkey.retromusic.db.MIGRATION_23_24
|
||||||
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
|
||||||
import code.name.monkey.retromusic.fragments.albums.AlbumDetailsViewModel
|
import code.name.monkey.retromusic.fragments.albums.AlbumDetailsViewModel
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.activities
|
package code.name.monkey.retromusic.activities
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.Manifest.permission.BLUETOOTH_CONNECT
|
import android.Manifest.permission.BLUETOOTH_CONNECT
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
@ -129,10 +128,7 @@ class PermissionActivity : AbsMusicServiceActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasStoragePermission(): Boolean {
|
private fun hasStoragePermission(): Boolean {
|
||||||
return ActivityCompat.checkSelfPermission(
|
return hasPermissions()
|
||||||
this,
|
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.S)
|
@RequiresApi(Build.VERSION_CODES.S)
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.view.ViewGroup
|
||||||
import android.webkit.WebResourceRequest
|
import android.webkit.WebResourceRequest
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.core.content.PackageManagerCompat
|
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import androidx.core.widget.NestedScrollView
|
import androidx.core.widget.NestedScrollView
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
@ -27,7 +26,7 @@ import code.name.monkey.retromusic.extensions.openUrl
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.lastVersion
|
import code.name.monkey.retromusic.util.PreferenceUtil.lastVersion
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.util.Locale
|
import java.util.*
|
||||||
|
|
||||||
class WhatsNewFragment : BottomSheetDialogFragment() {
|
class WhatsNewFragment : BottomSheetDialogFragment() {
|
||||||
private var _binding: FragmentWhatsNewBinding? = null
|
private var _binding: FragmentWhatsNewBinding? = null
|
||||||
|
|
|
@ -18,6 +18,7 @@ import android.Manifest
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
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
|
||||||
|
@ -96,8 +97,7 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventLi
|
||||||
filter.addAction(MEDIA_STORE_CHANGED)
|
filter.addAction(MEDIA_STORE_CHANGED)
|
||||||
filter.addAction(FAVORITE_STATE_CHANGED)
|
filter.addAction(FAVORITE_STATE_CHANGED)
|
||||||
|
|
||||||
registerReceiver(musicStateReceiver, filter)
|
ContextCompat.registerReceiver(this, musicStateReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
|
|
||||||
receiverRegistered = true
|
receiverRegistered = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +190,13 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventLi
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPermissionsToRequest(): Array<String> {
|
override fun getPermissionsToRequest(): Array<String> {
|
||||||
return mutableListOf(Manifest.permission.READ_EXTERNAL_STORAGE).apply {
|
return mutableListOf<String>().apply {
|
||||||
|
if (VersionUtils.hasT()) {
|
||||||
|
add(Manifest.permission.READ_MEDIA_AUDIO)
|
||||||
|
add(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
} else {
|
||||||
|
add(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
|
}
|
||||||
if (!VersionUtils.hasR()) {
|
if (!VersionUtils.hasR()) {
|
||||||
add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,16 @@ 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 onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
println("Handle back press ${bottomSheetBehavior.state}")
|
||||||
|
if (!handleBackPress()) {
|
||||||
|
remove()
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val bottomSheetCallbackList by lazy {
|
private val bottomSheetCallbackList by lazy {
|
||||||
object : BottomSheetCallback() {
|
object : BottomSheetCallback() {
|
||||||
|
|
||||||
|
@ -154,6 +164,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||||
|
onBackPressedCallback.isEnabled = newState == STATE_EXPANDED
|
||||||
when (newState) {
|
when (newState) {
|
||||||
STATE_EXPANDED -> {
|
STATE_EXPANDED -> {
|
||||||
onPanelExpanded()
|
onPanelExpanded()
|
||||||
|
@ -212,6 +223,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationBarColor = surfaceColor()
|
navigationBarColor = surfaceColor()
|
||||||
|
|
||||||
|
onBackPressedDispatcher.addCallback(onBackPressedCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupBottomSheet() {
|
private fun setupBottomSheet() {
|
||||||
|
@ -231,14 +244,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
|
||||||
if (bottomSheetBehavior.state == STATE_EXPANDED) {
|
if (bottomSheetBehavior.state == STATE_EXPANDED) {
|
||||||
setMiniPlayerAlphaProgress(1f)
|
setMiniPlayerAlphaProgress(1f)
|
||||||
}
|
}
|
||||||
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
|
|
||||||
override fun handleOnBackPressed() {
|
|
||||||
if (!handleBackPress()) {
|
|
||||||
remove()
|
|
||||||
onBackPressedDispatcher.onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -403,7 +408,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleBackPress(): Boolean {
|
private fun handleBackPress(): Boolean {
|
||||||
if (bottomSheetBehavior.peekHeight != 0 && playerFragment.onBackPressed()) return true
|
|
||||||
if (panelState == STATE_EXPANDED) {
|
if (panelState == STATE_EXPANDED) {
|
||||||
collapsePanel()
|
collapsePanel()
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -15,29 +15,28 @@
|
||||||
package code.name.monkey.retromusic.activities.base
|
package code.name.monkey.retromusic.activities.base
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
|
||||||
import android.os.Bundle
|
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 androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
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.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 java.util.*
|
|
||||||
|
|
||||||
abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
|
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
updateLocale()
|
||||||
updateTheme()
|
updateTheme()
|
||||||
hideStatusBar()
|
hideStatusBar()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -62,6 +61,14 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateLocale() {
|
||||||
|
val localeCode = PreferenceUtil.languageCode
|
||||||
|
if (PreferenceUtil.isLocaleAutoStorageEnabled) {
|
||||||
|
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(localeCode))
|
||||||
|
PreferenceUtil.isLocaleAutoStorageEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
super.onWindowFocusChanged(hasFocus)
|
super.onWindowFocusChanged(hasFocus)
|
||||||
if (hasFocus) {
|
if (hasFocus) {
|
||||||
|
@ -96,14 +103,7 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(newBase: Context?) {
|
override fun attachBaseContext(newBase: Context?) {
|
||||||
val code = PreferenceUtil.languageCode
|
super.attachBaseContext(newBase)
|
||||||
val locale = if (code == "auto") {
|
|
||||||
// Get the device default locale
|
|
||||||
ConfigurationCompat.getLocales(Resources.getSystem().configuration)[0]
|
|
||||||
} else {
|
|
||||||
Locale.forLanguageTag(code)
|
|
||||||
}
|
|
||||||
super.attachBaseContext(LanguageContextWrapper.wrap(newBase, locale))
|
|
||||||
installSplitCompat()
|
installSplitCompat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.IntRange
|
import androidx.annotation.IntRange
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.isAdaptiveColor
|
import code.name.monkey.retromusic.util.PreferenceUtil.isAdaptiveColor
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.languageCode
|
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.nowPlayingScreen
|
import code.name.monkey.retromusic.util.PreferenceUtil.nowPlayingScreen
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -106,6 +106,6 @@ class DeviceInfo(context: Context) {
|
||||||
baseTheme = PreferenceUtil.baseTheme
|
baseTheme = PreferenceUtil.baseTheme
|
||||||
nowPlayingTheme = context.getString(nowPlayingScreen.titleRes)
|
nowPlayingTheme = context.getString(nowPlayingScreen.titleRes)
|
||||||
isAdaptive = isAdaptiveColor
|
isAdaptive = isAdaptiveColor
|
||||||
selectedLang = languageCode
|
selectedLang = AppCompatDelegate.getApplicationLocales().toLanguageTags()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -29,6 +29,7 @@ import android.view.animation.OvershootInterpolator
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.IntentSenderRequest
|
import androidx.activity.result.IntentSenderRequest
|
||||||
|
import androidx.activity.result.PickVisualMediaRequest
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
@ -37,7 +38,6 @@ 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
|
||||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||||
import code.name.monkey.retromusic.activities.saf.SAFGuideActivity
|
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
import code.name.monkey.retromusic.extensions.colorButtons
|
import code.name.monkey.retromusic.extensions.colorButtons
|
||||||
import code.name.monkey.retromusic.extensions.hideSoftKeyboard
|
import code.name.monkey.retromusic.extensions.hideSoftKeyboard
|
||||||
|
@ -45,8 +45,8 @@ import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||||
import code.name.monkey.retromusic.model.ArtworkInfo
|
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.logD
|
import code.name.monkey.retromusic.util.logD
|
||||||
|
import code.name.monkey.retromusic.util.logE
|
||||||
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
|
||||||
|
@ -56,7 +56,6 @@ import org.jaudiotagger.audio.AudioFileIO
|
||||||
import org.jaudiotagger.tag.FieldKey
|
import org.jaudiotagger.tag.FieldKey
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Collections
|
|
||||||
|
|
||||||
abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
abstract val editorImage: ImageView
|
abstract val editorImage: ImageView
|
||||||
|
@ -100,7 +99,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TITLE)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TITLE)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +118,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.COMPOSER)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.COMPOSER)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +128,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +138,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ARTIST)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ARTIST)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +148,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +158,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.GENRE)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.GENRE)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +168,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.YEAR)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.YEAR)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +178,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TRACK)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TRACK)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +188,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.DISC_NO)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.DISC_NO)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +198,8 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
get() {
|
get() {
|
||||||
return try {
|
return try {
|
||||||
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.LYRICS)
|
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.LYRICS)
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,11 +217,17 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
|
logE(e)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val pickArtworkImage =
|
||||||
|
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
|
||||||
|
loadImageFromFile(uri)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
_binding = bindingInflater.invoke(layoutInflater)
|
_binding = bindingInflater.invoke(layoutInflater)
|
||||||
|
@ -252,14 +268,7 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startImagePicker() {
|
private fun startImagePicker() {
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
pickArtworkImage.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
|
||||||
intent.type = "image/*"
|
|
||||||
startActivityForResult(
|
|
||||||
Intent.createChooser(
|
|
||||||
intent,
|
|
||||||
getString(R.string.pick_from_local_storage)
|
|
||||||
), REQUEST_CODE_SELECT_IMAGE
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun loadCurrentImage()
|
protected abstract fun loadCurrentImage()
|
||||||
|
@ -360,9 +369,12 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
artworkInfo
|
artworkInfo
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val pendingIntent = MediaStore.createWriteRequest(contentResolver, getSongUris())
|
|
||||||
|
|
||||||
launcher.launch(IntentSenderRequest.Builder(pendingIntent).build())
|
if (cacheFiles.isNotEmpty()) {
|
||||||
|
val pendingIntent =
|
||||||
|
MediaStore.createWriteRequest(contentResolver, getSongUris())
|
||||||
|
launcher.launch(IntentSenderRequest.Builder(pendingIntent).build())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
TagWriter.writeTagsToFiles(
|
TagWriter.writeTagsToFiles(
|
||||||
this@AbsTagEditorActivity, AudioTagInfo(
|
this@AbsTagEditorActivity, AudioTagInfo(
|
||||||
|
@ -400,39 +412,14 @@ abstract class AbsTagEditorActivity<VB : ViewBinding> : AbsBaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lateinit var audioFile: AudioFile
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
|
|
||||||
super.onActivityResult(requestCode, resultCode, intent)
|
|
||||||
when (requestCode) {
|
|
||||||
REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
|
|
||||||
intent?.data?.let {
|
|
||||||
loadImageFromFile(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SAFGuideActivity.REQUEST_CODE_SAF_GUIDE -> {
|
|
||||||
SAFUtil.openTreePicker(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
SAFUtil.REQUEST_SAF_PICK_TREE -> {
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
SAFUtil.saveTreeUri(this, intent)
|
|
||||||
writeTags(savedSongPaths)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SAFUtil.REQUEST_SAF_PICK_FILE -> {
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
writeTags(Collections.singletonList(currentSongPath + SAFUtil.SEPARATOR + intent!!.dataString))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun getAudioFile(path: String): AudioFile {
|
private fun getAudioFile(path: String): AudioFile {
|
||||||
return try {
|
return try {
|
||||||
AudioFileIO.read(File(path))
|
if (!this::audioFile.isInitialized) {
|
||||||
|
audioFile = AudioFileIO.read(File(path))
|
||||||
|
}
|
||||||
|
audioFile
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Could not read audio file $path", e)
|
Log.e(TAG, "Could not read audio file $path", e)
|
||||||
AudioFile()
|
AudioFile()
|
||||||
|
|
|
@ -30,11 +30,7 @@ import androidx.core.widget.doAfterTextChanged
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.ActivityAlbumTagEditorBinding
|
import code.name.monkey.retromusic.databinding.ActivityAlbumTagEditorBinding
|
||||||
import code.name.monkey.retromusic.extensions.appHandleColor
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.defaultFooterColor
|
|
||||||
import code.name.monkey.retromusic.extensions.isColorLight
|
|
||||||
import code.name.monkey.retromusic.extensions.setTint
|
|
||||||
import code.name.monkey.retromusic.extensions.showToast
|
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
|
import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
|
||||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||||
import code.name.monkey.retromusic.model.ArtworkInfo
|
import code.name.monkey.retromusic.model.ArtworkInfo
|
||||||
|
@ -50,7 +46,7 @@ import com.bumptech.glide.request.target.ImageViewTarget
|
||||||
import com.bumptech.glide.request.transition.Transition
|
import com.bumptech.glide.request.transition.Transition
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import org.jaudiotagger.tag.FieldKey
|
import org.jaudiotagger.tag.FieldKey
|
||||||
import java.util.EnumMap
|
import java.util.*
|
||||||
|
|
||||||
class AlbumTagEditorActivity : AbsTagEditorActivity<ActivityAlbumTagEditorBinding>() {
|
class AlbumTagEditorActivity : AbsTagEditorActivity<ActivityAlbumTagEditorBinding>() {
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.media.MediaScannerConnection
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.extensions.showToast
|
import code.name.monkey.retromusic.extensions.showToast
|
||||||
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener
|
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener
|
||||||
import code.name.monkey.retromusic.model.AudioTagInfo
|
import code.name.monkey.retromusic.model.AudioTagInfo
|
||||||
|
@ -20,6 +21,7 @@ import org.jaudiotagger.audio.exceptions.CannotReadException
|
||||||
import org.jaudiotagger.audio.exceptions.CannotWriteException
|
import org.jaudiotagger.audio.exceptions.CannotWriteException
|
||||||
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException
|
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException
|
||||||
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException
|
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException
|
||||||
|
import org.jaudiotagger.tag.FieldDataInvalidException
|
||||||
import org.jaudiotagger.tag.TagException
|
import org.jaudiotagger.tag.TagException
|
||||||
import org.jaudiotagger.tag.images.AndroidArtwork
|
import org.jaudiotagger.tag.images.AndroidArtwork
|
||||||
import org.jaudiotagger.tag.images.Artwork
|
import org.jaudiotagger.tag.images.Artwork
|
||||||
|
@ -31,9 +33,9 @@ class TagWriter {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
suspend fun scan(context: Context, toBeScanned: List<String?>?) {
|
suspend fun scan(context: Context, toBeScanned: List<String?>?) {
|
||||||
if (toBeScanned == null || toBeScanned.isEmpty()) {
|
if (toBeScanned.isNullOrEmpty()) {
|
||||||
Log.i("scan", "scan: Empty")
|
Log.i("scan", "scan: Empty")
|
||||||
context.showToast( "Scan file from folder")
|
context.showToast("Scan file from folder")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
MediaScannerConnection.scanFile(
|
MediaScannerConnection.scanFile(
|
||||||
|
@ -50,150 +52,151 @@ class TagWriter {
|
||||||
|
|
||||||
suspend fun writeTagsToFiles(context: Context, info: AudioTagInfo) {
|
suspend fun writeTagsToFiles(context: Context, info: AudioTagInfo) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
runCatching {
|
var artwork: Artwork? = null
|
||||||
var artwork: Artwork? = null
|
var albumArtFile: File? = null
|
||||||
var albumArtFile: File? = null
|
if (info.artworkInfo?.artwork != null) {
|
||||||
if (info.artworkInfo?.artwork != null) {
|
try {
|
||||||
try {
|
albumArtFile = createAlbumArtFile(context).canonicalFile
|
||||||
albumArtFile = createAlbumArtFile(context).canonicalFile
|
info.artworkInfo.artwork.compress(
|
||||||
info.artworkInfo.artwork.compress(
|
Bitmap.CompressFormat.JPEG,
|
||||||
Bitmap.CompressFormat.JPEG,
|
100,
|
||||||
100,
|
albumArtFile.outputStream()
|
||||||
albumArtFile.outputStream()
|
)
|
||||||
)
|
artwork = AndroidArtwork.createArtworkFromFile(albumArtFile)
|
||||||
artwork = AndroidArtwork.createArtworkFromFile(albumArtFile)
|
} catch (e: IOException) {
|
||||||
} catch (e: IOException) {
|
e.printStackTrace()
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var wroteArtwork = false
|
|
||||||
var deletedArtwork = false
|
|
||||||
for (filePath in info.filePaths!!) {
|
|
||||||
try {
|
|
||||||
val audioFile = AudioFileIO.read(File(filePath))
|
|
||||||
val tag = audioFile.tagOrCreateAndSetDefault
|
|
||||||
if (info.fieldKeyValueMap != null) {
|
|
||||||
for ((key, value) in info.fieldKeyValueMap) {
|
|
||||||
try {
|
|
||||||
tag.setField(key, value)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (info.artworkInfo != null) {
|
|
||||||
if (info.artworkInfo.artwork == null) {
|
|
||||||
tag.deleteArtworkField()
|
|
||||||
deletedArtwork = true
|
|
||||||
} else if (artwork != null) {
|
|
||||||
tag.deleteArtworkField()
|
|
||||||
tag.setField(artwork)
|
|
||||||
wroteArtwork = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
audioFile.commit()
|
|
||||||
} catch (e: CannotReadException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: CannotWriteException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: TagException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: ReadOnlyFileException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: InvalidAudioFrameException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wroteArtwork) {
|
|
||||||
insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path)
|
|
||||||
} else if (deletedArtwork) {
|
|
||||||
deleteAlbumArt(context, info.artworkInfo!!.albumId)
|
|
||||||
}
|
|
||||||
scan(context, info.filePaths)
|
|
||||||
}.onFailure {
|
|
||||||
it.printStackTrace()
|
|
||||||
}
|
}
|
||||||
|
var wroteArtwork = false
|
||||||
|
var deletedArtwork = false
|
||||||
|
for (filePath in info.filePaths!!) {
|
||||||
|
try {
|
||||||
|
val audioFile = AudioFileIO.read(File(filePath))
|
||||||
|
val tag = audioFile.tagOrCreateAndSetDefault
|
||||||
|
if (info.fieldKeyValueMap != null) {
|
||||||
|
for ((key, value) in info.fieldKeyValueMap) {
|
||||||
|
try {
|
||||||
|
tag.setField(key, value)
|
||||||
|
} catch (e: FieldDataInvalidException) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
context.showToast(R.string.could_not_write_tags_to_file)
|
||||||
|
}
|
||||||
|
return@withContext listOf<File>()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (info.artworkInfo != null) {
|
||||||
|
if (info.artworkInfo.artwork == null) {
|
||||||
|
tag.deleteArtworkField()
|
||||||
|
deletedArtwork = true
|
||||||
|
} else if (artwork != null) {
|
||||||
|
tag.deleteArtworkField()
|
||||||
|
tag.setField(artwork)
|
||||||
|
wroteArtwork = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
audioFile.commit()
|
||||||
|
} catch (e: CannotReadException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: CannotWriteException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: TagException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: ReadOnlyFileException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: InvalidAudioFrameException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wroteArtwork) {
|
||||||
|
insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path)
|
||||||
|
} else if (deletedArtwork) {
|
||||||
|
deleteAlbumArt(context, info.artworkInfo!!.albumId)
|
||||||
|
}
|
||||||
|
scan(context, info.filePaths)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
suspend fun writeTagsToFilesR(context: Context, info: AudioTagInfo): List<File> =
|
suspend fun writeTagsToFilesR(context: Context, info: AudioTagInfo): List<File> =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val cacheFiles = mutableListOf<File>()
|
val cacheFiles = mutableListOf<File>()
|
||||||
runCatching {
|
var artwork: Artwork? = null
|
||||||
var artwork: Artwork? = null
|
var albumArtFile: File? = null
|
||||||
var albumArtFile: File? = null
|
if (info.artworkInfo?.artwork != null) {
|
||||||
if (info.artworkInfo?.artwork != null) {
|
try {
|
||||||
try {
|
albumArtFile = createAlbumArtFile(context).canonicalFile
|
||||||
albumArtFile = createAlbumArtFile(context).canonicalFile
|
info.artworkInfo.artwork.compress(
|
||||||
info.artworkInfo.artwork.compress(
|
Bitmap.CompressFormat.JPEG,
|
||||||
Bitmap.CompressFormat.JPEG,
|
100,
|
||||||
100,
|
albumArtFile.outputStream()
|
||||||
albumArtFile.outputStream()
|
)
|
||||||
)
|
artwork = AndroidArtwork.createArtworkFromFile(albumArtFile)
|
||||||
artwork = AndroidArtwork.createArtworkFromFile(albumArtFile)
|
} catch (e: IOException) {
|
||||||
} catch (e: IOException) {
|
e.printStackTrace()
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var wroteArtwork = false
|
}
|
||||||
var deletedArtwork = false
|
var wroteArtwork = false
|
||||||
for (filePath in info.filePaths!!) {
|
var deletedArtwork = false
|
||||||
try {
|
for (filePath in info.filePaths!!) {
|
||||||
val originFile = File(filePath)
|
try {
|
||||||
val cacheFile = File(context.cacheDir, originFile.name)
|
val originFile = File(filePath)
|
||||||
cacheFiles.add(cacheFile)
|
val cacheFile = File(context.cacheDir, originFile.name)
|
||||||
originFile.inputStream().use { input ->
|
cacheFiles.add(cacheFile)
|
||||||
cacheFile.outputStream().use { output ->
|
originFile.inputStream().use { input ->
|
||||||
input.copyTo(output)
|
cacheFile.outputStream().use { output ->
|
||||||
}
|
input.copyTo(output)
|
||||||
}
|
}
|
||||||
val audioFile = AudioFileIO.read(cacheFile)
|
}
|
||||||
val tag = audioFile.tagOrCreateAndSetDefault
|
val audioFile = AudioFileIO.read(cacheFile)
|
||||||
if (info.fieldKeyValueMap != null) {
|
val tag = audioFile.tagOrCreateAndSetDefault
|
||||||
for ((key, value) in info.fieldKeyValueMap) {
|
if (info.fieldKeyValueMap != null) {
|
||||||
try {
|
for ((key, value) in info.fieldKeyValueMap) {
|
||||||
tag.setField(key, value)
|
try {
|
||||||
} catch (e: Exception) {
|
tag.setField(key, value)
|
||||||
e.printStackTrace()
|
} catch (e: FieldDataInvalidException) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
context.showToast(R.string.could_not_write_tags_to_file)
|
||||||
}
|
}
|
||||||
|
return@withContext listOf<File>()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.artworkInfo != null) {
|
|
||||||
if (info.artworkInfo.artwork == null) {
|
|
||||||
tag.deleteArtworkField()
|
|
||||||
deletedArtwork = true
|
|
||||||
} else if (artwork != null) {
|
|
||||||
tag.deleteArtworkField()
|
|
||||||
tag.setField(artwork)
|
|
||||||
wroteArtwork = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
audioFile.commit()
|
|
||||||
} catch (e: CannotReadException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: CannotWriteException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: TagException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: ReadOnlyFileException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: InvalidAudioFrameException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
|
if (info.artworkInfo != null) {
|
||||||
|
if (info.artworkInfo.artwork == null) {
|
||||||
|
tag.deleteArtworkField()
|
||||||
|
deletedArtwork = true
|
||||||
|
} else if (artwork != null) {
|
||||||
|
tag.deleteArtworkField()
|
||||||
|
tag.setField(artwork)
|
||||||
|
wroteArtwork = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
audioFile.commit()
|
||||||
|
} catch (e: CannotReadException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: CannotWriteException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: TagException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: ReadOnlyFileException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: InvalidAudioFrameException) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
if (wroteArtwork) {
|
}
|
||||||
insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path)
|
if (wroteArtwork) {
|
||||||
} else if (deletedArtwork) {
|
insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path)
|
||||||
deleteAlbumArt(context, info.artworkInfo!!.albumId)
|
} else if (deletedArtwork) {
|
||||||
}
|
deleteAlbumArt(context, info.artworkInfo!!.albumId)
|
||||||
}.onFailure {
|
|
||||||
it.printStackTrace()
|
|
||||||
}
|
}
|
||||||
cacheFiles
|
cacheFiles
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,7 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.MainActivity
|
import code.name.monkey.retromusic.activities.MainActivity
|
||||||
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
|
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.Card
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.Classic
|
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.Fit
|
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.Full
|
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.Gradient
|
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.Peek
|
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen.Tiny
|
|
||||||
import code.name.monkey.retromusic.fragments.base.goToLyrics
|
import code.name.monkey.retromusic.fragments.base.goToLyrics
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
|
import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
|
||||||
|
|
|
@ -26,6 +26,7 @@ import code.name.monkey.retromusic.db.toSongsEntity
|
||||||
import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog
|
import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.util.ViewUtil
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter
|
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
|
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -50,11 +51,7 @@ class OrderablePlaylistSongAdapter(
|
||||||
override fun getItemId(position: Int): Long {
|
override fun getItemId(position: Int): Long {
|
||||||
// requires static value, it means need to keep the same value
|
// requires static value, it means need to keep the same value
|
||||||
// even if the item position has been changed.
|
// even if the item position has been changed.
|
||||||
return if (position != 0) {
|
return dataSet[position].id
|
||||||
dataSet[position - 1].id
|
|
||||||
} else {
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createViewHolder(view: View): SongAdapter.ViewHolder {
|
override fun createViewHolder(view: View): SongAdapter.ViewHolder {
|
||||||
|
@ -99,26 +96,22 @@ class OrderablePlaylistSongAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean {
|
override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean {
|
||||||
if (dataSet.size == 0 or 1 || isInQuickSelectMode) {
|
if (isInQuickSelectMode) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val dragHandle = holder.dragView ?: return false
|
return ViewUtil.hitTest(holder.imageText!!, x, y) || ViewUtil.hitTest(
|
||||||
|
holder.dragView!!,
|
||||||
val handleWidth = dragHandle.width
|
x,
|
||||||
val handleHeight = dragHandle.height
|
y
|
||||||
val handleLeft = dragHandle.left
|
)
|
||||||
val handleTop = dragHandle.top
|
|
||||||
|
|
||||||
return (x >= handleLeft && x < handleLeft + handleWidth &&
|
|
||||||
y >= handleTop && y < handleTop + handleHeight) && position != 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMoveItem(fromPosition: Int, toPosition: Int) {
|
override fun onMoveItem(fromPosition: Int, toPosition: Int) {
|
||||||
dataSet.add(toPosition - 1, dataSet.removeAt(fromPosition - 1))
|
dataSet.add(toPosition, dataSet.removeAt(fromPosition))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange {
|
override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange? {
|
||||||
return ItemDraggableRange(0, itemCount - 1)
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCheckCanDrop(draggingPosition: Int, dropPosition: Int): Boolean {
|
override fun onCheckCanDrop(draggingPosition: Int, dropPosition: Int): Boolean {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.DimenRes
|
import androidx.annotation.DimenRes
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.os.BundleCompat
|
|
||||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,7 @@ import android.app.ActivityOptions
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
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.SubMenu
|
|
||||||
import android.view.View
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.text.parseAsHtml
|
import androidx.core.text.parseAsHtml
|
||||||
|
@ -47,11 +43,7 @@ import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
|
||||||
import code.name.monkey.retromusic.databinding.FragmentAlbumDetailsBinding
|
import code.name.monkey.retromusic.databinding.FragmentAlbumDetailsBinding
|
||||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||||
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
|
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.applyOutlineColor
|
|
||||||
import code.name.monkey.retromusic.extensions.findActivityNavController
|
|
||||||
import code.name.monkey.retromusic.extensions.show
|
|
||||||
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.glide.RetroGlideExtension
|
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension.albumCoverOptions
|
import code.name.monkey.retromusic.glide.RetroGlideExtension.albumCoverOptions
|
||||||
|
@ -69,11 +61,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.RetroUtil
|
|
||||||
import code.name.monkey.retromusic.util.logD
|
|
||||||
import code.name.monkey.retromusic.util.logE
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.transition.MaterialArcMotion
|
import com.google.android.material.transition.MaterialArcMotion
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package code.name.monkey.retromusic.fragments.artists
|
package code.name.monkey.retromusic.fragments.artists
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
|
@ -9,6 +7,7 @@ import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.activity.result.PickVisualMediaRequest
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
@ -27,11 +26,7 @@ import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
|
||||||
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
|
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
|
||||||
import code.name.monkey.retromusic.databinding.FragmentArtistDetailsBinding
|
import code.name.monkey.retromusic.databinding.FragmentArtistDetailsBinding
|
||||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.applyOutlineColor
|
|
||||||
import code.name.monkey.retromusic.extensions.show
|
|
||||||
import code.name.monkey.retromusic.extensions.showToast
|
|
||||||
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.glide.RetroGlideExtension
|
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension.artistImageOptions
|
import code.name.monkey.retromusic.glide.RetroGlideExtension.artistImageOptions
|
||||||
|
@ -44,12 +39,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.LastFmArtist
|
import code.name.monkey.retromusic.network.model.LastFmArtist
|
||||||
import code.name.monkey.retromusic.repository.RealRepository
|
import code.name.monkey.retromusic.repository.RealRepository
|
||||||
import code.name.monkey.retromusic.util.CustomArtistImageUtil
|
import code.name.monkey.retromusic.util.*
|
||||||
import code.name.monkey.retromusic.util.MusicUtil
|
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
|
||||||
import code.name.monkey.retromusic.util.logD
|
|
||||||
import code.name.monkey.retromusic.util.logE
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.transition.MaterialContainerTransform
|
import com.google.android.material.transition.MaterialContainerTransform
|
||||||
|
@ -57,7 +47,7 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.koin.android.ext.android.get
|
import org.koin.android.ext.android.get
|
||||||
import java.util.Locale
|
import java.util.*
|
||||||
|
|
||||||
abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_details),
|
abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_details),
|
||||||
IAlbumClickListener {
|
IAlbumClickListener {
|
||||||
|
@ -153,14 +143,10 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs))
|
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs))
|
||||||
)
|
)
|
||||||
val songText = resources.getQuantityString(
|
val songText = resources.getQuantityString(
|
||||||
R.plurals.albumSongs,
|
R.plurals.albumSongs, artist.songCount, artist.songCount
|
||||||
artist.songCount,
|
|
||||||
artist.songCount
|
|
||||||
)
|
)
|
||||||
val albumText = resources.getQuantityString(
|
val albumText = resources.getQuantityString(
|
||||||
R.plurals.albums,
|
R.plurals.albums, artist.songCount, artist.songCount
|
||||||
artist.songCount,
|
|
||||||
artist.songCount
|
|
||||||
)
|
)
|
||||||
binding.fragmentArtistContent.songTitle.text = songText
|
binding.fragmentArtistContent.songTitle.text = songText
|
||||||
binding.fragmentArtistContent.albumTitle.text = albumText
|
binding.fragmentArtistContent.albumTitle.text = albumText
|
||||||
|
@ -174,8 +160,7 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
) {
|
) {
|
||||||
biography = null
|
biography = null
|
||||||
this.lang = lang
|
this.lang = lang
|
||||||
detailsViewModel.getArtistInfo(name, lang, null)
|
detailsViewModel.getArtistInfo(name, lang, null).observe(viewLifecycleOwner) { result ->
|
||||||
.observe(viewLifecycleOwner) { result ->
|
|
||||||
when (result) {
|
when (result) {
|
||||||
is Result.Loading -> logD("Loading")
|
is Result.Loading -> logD("Loading")
|
||||||
is Result.Error -> logE("Error")
|
is Result.Error -> logE("Error")
|
||||||
|
@ -214,11 +199,8 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadArtistImage(artist: Artist) {
|
private fun loadArtistImage(artist: Artist) {
|
||||||
Glide.with(requireContext())
|
Glide.with(requireContext()).asBitmapPalette().artistImageOptions(artist)
|
||||||
.asBitmapPalette()
|
.load(RetroGlideExtension.getArtistModel(artist)).dontAnimate()
|
||||||
.artistImageOptions(artist)
|
|
||||||
.load(RetroGlideExtension.getArtistModel(artist))
|
|
||||||
.dontAnimate()
|
|
||||||
.into(object : SingleColorTarget(binding.image) {
|
.into(object : SingleColorTarget(binding.image) {
|
||||||
override fun onColorReady(color: Int) {
|
override fun onColorReady(color: Int) {
|
||||||
setColors(color)
|
setColors(color)
|
||||||
|
@ -274,13 +256,8 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_set_artist_image -> {
|
R.id.action_set_artist_image -> {
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
|
||||||
intent.type = "image/*"
|
|
||||||
selectImageLauncher.launch(
|
selectImageLauncher.launch(
|
||||||
Intent.createChooser(
|
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
|
||||||
intent,
|
|
||||||
getString(R.string.pick_from_local_storage)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -336,14 +313,14 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
SortOrder.ArtistSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc).isChecked =
|
SortOrder.ArtistSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc).isChecked =
|
||||||
true
|
true
|
||||||
|
|
||||||
SortOrder.ArtistSongSortOrder.SONG_ALBUM ->
|
SortOrder.ArtistSongSortOrder.SONG_ALBUM -> sortOrder.findItem(R.id.action_sort_order_album).isChecked =
|
||||||
sortOrder.findItem(R.id.action_sort_order_album).isChecked = true
|
true
|
||||||
|
|
||||||
SortOrder.ArtistSongSortOrder.SONG_YEAR ->
|
SortOrder.ArtistSongSortOrder.SONG_YEAR -> sortOrder.findItem(R.id.action_sort_order_year).isChecked =
|
||||||
sortOrder.findItem(R.id.action_sort_order_year).isChecked = true
|
true
|
||||||
|
|
||||||
SortOrder.ArtistSongSortOrder.SONG_DURATION ->
|
SortOrder.ArtistSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_song_duration).isChecked =
|
||||||
sortOrder.findItem(R.id.action_sort_order_song_duration).isChecked = true
|
true
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalArgumentException("invalid $savedSongSortOrder")
|
throw IllegalArgumentException("invalid $savedSongSortOrder")
|
||||||
|
@ -352,14 +329,11 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
}
|
}
|
||||||
|
|
||||||
private val selectImageLauncher =
|
private val selectImageLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
lifecycleScope.launch {
|
||||||
result.data?.data?.let {
|
if (uri != null) {
|
||||||
lifecycleScope.launch {
|
CustomArtistImageUtil.getInstance(requireContext())
|
||||||
CustomArtistImageUtil.getInstance(requireContext())
|
.setCustomArtistImage(artist, uri)
|
||||||
.setCustomArtistImage(artist, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import code.name.monkey.retromusic.R
|
|
||||||
import code.name.monkey.retromusic.databinding.ActivityRestoreBinding
|
import code.name.monkey.retromusic.databinding.ActivityRestoreBinding
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
import code.name.monkey.retromusic.extensions.accentOutlineColor
|
import code.name.monkey.retromusic.extensions.accentOutlineColor
|
||||||
|
|
|
@ -248,8 +248,6 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMusicServiceFragme
|
||||||
|
|
||||||
abstract fun onHide()
|
abstract fun onHide()
|
||||||
|
|
||||||
abstract fun onBackPressed(): Boolean
|
|
||||||
|
|
||||||
abstract fun toolbarIconColor(): Int
|
abstract fun toolbarIconColor(): Int
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
override fun onServiceConnected() {
|
||||||
|
|
|
@ -17,11 +17,7 @@ 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.view.ViewGroup
|
|
||||||
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
|
||||||
|
@ -77,8 +73,7 @@ import java.io.File
|
||||||
import java.io.FileFilter
|
import java.io.FileFilter
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.Collections
|
import java.util.*
|
||||||
import java.util.LinkedList
|
|
||||||
|
|
||||||
class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
IMainActivityFragmentCallbacks, SelectionCallback, ICallbacks,
|
IMainActivityFragmentCallbacks, SelectionCallback, ICallbacks,
|
||||||
|
|
|
@ -15,12 +15,8 @@
|
||||||
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 android.view.ViewGroup
|
|
||||||
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
|
||||||
|
@ -34,18 +30,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.EXTRA_PLAYLIST_TYPE
|
import code.name.monkey.retromusic.*
|
||||||
import code.name.monkey.retromusic.HISTORY_PLAYLIST
|
|
||||||
import code.name.monkey.retromusic.LAST_ADDED_PLAYLIST
|
|
||||||
import code.name.monkey.retromusic.R
|
|
||||||
import code.name.monkey.retromusic.TOP_PLAYED_PLAYLIST
|
|
||||||
import code.name.monkey.retromusic.adapter.HomeAdapter
|
import code.name.monkey.retromusic.adapter.HomeAdapter
|
||||||
import code.name.monkey.retromusic.databinding.FragmentHomeBinding
|
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.dip
|
||||||
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.extensions.setUpMediaRouteButton
|
import code.name.monkey.retromusic.extensions.setUpMediaRouteButton
|
||||||
import code.name.monkey.retromusic.fragments.ReloadType
|
import code.name.monkey.retromusic.fragments.ReloadType
|
||||||
|
@ -60,7 +51,6 @@ import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
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.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
|
||||||
import com.google.android.material.transition.MaterialFadeThrough
|
import com.google.android.material.transition.MaterialFadeThrough
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
|
||||||
|
@ -175,7 +165,7 @@ class HomeFragment :
|
||||||
findNavController().navigate(R.id.action_search, null, navOptions)
|
findNavController().navigate(R.id.action_search, null, navOptions)
|
||||||
}
|
}
|
||||||
val hexColor = String.format("#%06X", 0xFFFFFF and accentColor())
|
val hexColor = String.format("#%06X", 0xFFFFFF and accentColor())
|
||||||
val appName = "<font color=$hexColor>Retro Music</font>".parseAsHtml()
|
val appName = "Retro <font color=$hexColor>Music</font>".parseAsHtml()
|
||||||
binding.appBarLayout.title = appName
|
binding.appBarLayout.title = appName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,7 @@ import androidx.appcompat.widget.Toolbar
|
||||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentAdaptivePlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentAdaptivePlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
|
||||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
|
||||||
import code.name.monkey.retromusic.extensions.textColorPrimary
|
|
||||||
import code.name.monkey.retromusic.extensions.textColorSecondary
|
|
||||||
import code.name.monkey.retromusic.extensions.whichFragment
|
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
|
@ -118,11 +113,6 @@ class AdaptiveFragment : AbsPlayerFragment(R.layout.fragment_adaptive_player) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -106,10 +106,6 @@ class BlurPlayerFragment : AbsPlayerFragment(R.layout.fragment_blur),
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
return Color.WHITE
|
return Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,6 @@ class CardFragment : AbsPlayerFragment(R.layout.fragment_card_player) {
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
playbackControlsFragment.hide()
|
playbackControlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
|
|
|
@ -62,11 +62,6 @@ class CardBlurFragment : AbsPlayerFragment(R.layout.fragment_card_blur_player),
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
playbackControlsFragment.hide()
|
playbackControlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
|
|
|
@ -195,8 +195,6 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean = false
|
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int =
|
override fun toolbarIconColor(): Int =
|
||||||
colorControlNormal()
|
colorControlNormal()
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ 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 android.widget.SeekBar
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
|
@ -163,6 +164,13 @@ class ClassicPlayerFragment : AbsPlayerFragment(R.layout.fragment_classic_player
|
||||||
binding.text.setOnClickListener {
|
binding.text.setOnClickListener {
|
||||||
goToArtist(requireActivity())
|
goToArtist(requireActivity())
|
||||||
}
|
}
|
||||||
|
requireActivity().onBackPressedDispatcher.addCallback(object: OnBackPressedCallback(true) {
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
if (getQueuePanel().state == BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
|
getQueuePanel().state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideVolumeIfAvailable() {
|
private fun hideVolumeIfAvailable() {
|
||||||
|
@ -257,16 +265,6 @@ class ClassicPlayerFragment : AbsPlayerFragment(R.layout.fragment_classic_player
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
var wasExpanded = false
|
|
||||||
if (getQueuePanel().state == BottomSheetBehavior.STATE_EXPANDED) {
|
|
||||||
wasExpanded = getQueuePanel().state == BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
getQueuePanel().state = BottomSheetBehavior.STATE_COLLAPSED
|
|
||||||
return wasExpanded
|
|
||||||
}
|
|
||||||
return wasExpanded
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
return Color.WHITE
|
return Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,11 +79,6 @@ class ColorFragment : AbsPlayerFragment(R.layout.fragment_color_player) {
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
playbackControlsFragment.hide()
|
playbackControlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
|
|
|
@ -49,11 +49,6 @@ class FitFragment : AbsPlayerFragment(R.layout.fragment_fit) {
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
playbackControlsFragment.hide()
|
playbackControlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
|
|
|
@ -100,11 +100,6 @@ class FlatPlayerFragment : AbsPlayerFragment(R.layout.fragment_flat_player) {
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
controlsFragment.hide()
|
controlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
|
|
|
@ -32,11 +32,7 @@ import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentFullPlayerControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentFullPlayerControlsBinding
|
||||||
import code.name.monkey.retromusic.db.PlaylistEntity
|
import code.name.monkey.retromusic.db.PlaylistEntity
|
||||||
import code.name.monkey.retromusic.db.toSongEntity
|
import code.name.monkey.retromusic.db.toSongEntity
|
||||||
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.getTintedDrawable
|
|
||||||
import code.name.monkey.retromusic.extensions.hide
|
|
||||||
import code.name.monkey.retromusic.extensions.show
|
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
import code.name.monkey.retromusic.fragments.ReloadType
|
import code.name.monkey.retromusic.fragments.ReloadType
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
|
|
@ -86,10 +86,6 @@ class FullPlayerFragment : AbsPlayerFragment(R.layout.fragment_full) {
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
return Color.WHITE
|
return Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import android.graphics.PorterDuff
|
||||||
import android.graphics.drawable.AnimatedVectorDrawable
|
import android.graphics.drawable.AnimatedVectorDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
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
|
||||||
|
@ -94,16 +95,19 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||||
|
onBackPressedCallback.isEnabled = newState == STATE_EXPANDED
|
||||||
when (newState) {
|
when (newState) {
|
||||||
STATE_EXPANDED,
|
STATE_EXPANDED,
|
||||||
STATE_DRAGGING,
|
STATE_DRAGGING,
|
||||||
-> {
|
-> {
|
||||||
mainActivity.getBottomSheetBehavior().isDraggable = false
|
mainActivity.getBottomSheetBehavior().isDraggable = false
|
||||||
}
|
}
|
||||||
|
|
||||||
STATE_COLLAPSED -> {
|
STATE_COLLAPSED -> {
|
||||||
resetToCurrentPosition()
|
resetToCurrentPosition()
|
||||||
mainActivity.getBottomSheetBehavior().isDraggable = true
|
mainActivity.getBottomSheetBehavior().isDraggable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
mainActivity.getBottomSheetBehavior().isDraggable = true
|
mainActivity.getBottomSheetBehavior().isDraggable = true
|
||||||
}
|
}
|
||||||
|
@ -111,6 +115,17 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
if (getQueuePanel().state == STATE_EXPANDED) {
|
||||||
|
getQueuePanel().state = STATE_COLLAPSED
|
||||||
|
} else {
|
||||||
|
isEnabled = false
|
||||||
|
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupFavourite() {
|
private fun setupFavourite() {
|
||||||
binding.playbackControlsFragment.songFavourite.setOnClickListener {
|
binding.playbackControlsFragment.songFavourite.setOnClickListener {
|
||||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||||
|
@ -164,6 +179,10 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
insets
|
insets
|
||||||
}
|
}
|
||||||
binding.playbackControlsFragment.root.drawAboveSystemBars()
|
binding.playbackControlsFragment.root.drawAboveSystemBars()
|
||||||
|
requireActivity().onBackPressedDispatcher.addCallback(
|
||||||
|
viewLifecycleOwner,
|
||||||
|
onBackPressedCallback
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@ -201,16 +220,6 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
var wasExpanded = false
|
|
||||||
if (getQueuePanel().state == STATE_EXPANDED) {
|
|
||||||
wasExpanded = getQueuePanel().state == STATE_EXPANDED
|
|
||||||
getQueuePanel().state = STATE_COLLAPSED
|
|
||||||
return wasExpanded
|
|
||||||
}
|
|
||||||
return wasExpanded
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
return Color.WHITE
|
return Color.WHITE
|
||||||
}
|
}
|
||||||
|
@ -417,6 +426,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
lastPlaybackControlsColor,
|
lastPlaybackControlsColor,
|
||||||
PorterDuff.Mode.SRC_IN
|
PorterDuff.Mode.SRC_IN
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> binding.shuffleButton.setColorFilter(
|
else -> binding.shuffleButton.setColorFilter(
|
||||||
lastDisabledPlaybackControlsColor,
|
lastDisabledPlaybackControlsColor,
|
||||||
PorterDuff.Mode.SRC_IN
|
PorterDuff.Mode.SRC_IN
|
||||||
|
@ -437,6 +447,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
PorterDuff.Mode.SRC_IN
|
PorterDuff.Mode.SRC_IN
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicService.REPEAT_MODE_ALL -> {
|
MusicService.REPEAT_MODE_ALL -> {
|
||||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
binding.repeatButton.setImageResource(R.drawable.ic_repeat)
|
||||||
binding.repeatButton.setColorFilter(
|
binding.repeatButton.setColorFilter(
|
||||||
|
@ -444,6 +455,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
PorterDuff.Mode.SRC_IN
|
PorterDuff.Mode.SRC_IN
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicService.REPEAT_MODE_THIS -> {
|
MusicService.REPEAT_MODE_THIS -> {
|
||||||
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
|
||||||
binding.repeatButton.setColorFilter(
|
binding.repeatButton.setColorFilter(
|
||||||
|
|
|
@ -84,10 +84,6 @@ class HomePlayerFragment : AbsPlayerFragment(R.layout.fragment_home_player),
|
||||||
binding.text.text = song.artistName
|
binding.text.text = song.artistName
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
return Color.WHITE
|
return Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,11 +90,6 @@ class MaterialFragment : AbsPlayerFragment(R.layout.fragment_material) {
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
playbackControlsFragment.hide()
|
playbackControlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor() = colorControlNormal()
|
override fun toolbarIconColor() = colorControlNormal()
|
||||||
|
|
|
@ -45,11 +45,6 @@ class MD3PlayerFragment : AbsPlayerFragment(R.layout.fragment_md3_player) {
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
controlsFragment.hide()
|
controlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
|
|
|
@ -27,11 +27,7 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.SNOWFALL
|
import code.name.monkey.retromusic.SNOWFALL
|
||||||
import code.name.monkey.retromusic.databinding.FragmentPlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentPlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
|
||||||
import code.name.monkey.retromusic.extensions.isColorLight
|
|
||||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
|
||||||
import code.name.monkey.retromusic.extensions.whichFragment
|
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
|
@ -86,11 +82,6 @@ class PlayerFragment : AbsPlayerFragment(R.layout.fragment_player),
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
controlsFragment.hide()
|
controlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor() = colorControlNormal()
|
override fun toolbarIconColor() = colorControlNormal()
|
||||||
|
|
|
@ -20,12 +20,7 @@ import androidx.appcompat.widget.Toolbar
|
||||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentPeekPlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentPeekPlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBarsWithPadding
|
|
||||||
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.extensions.whichFragment
|
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
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
|
||||||
|
@ -93,10 +88,6 @@ class PeekPlayerFragment : AbsPlayerFragment(R.layout.fragment_peek_player) {
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor() = colorControlNormal()
|
override fun toolbarIconColor() = colorControlNormal()
|
||||||
|
|
||||||
override val paletteColor: Int
|
override val paletteColor: Int
|
||||||
|
|
|
@ -102,11 +102,6 @@ class PlainPlayerFragment : AbsPlayerFragment(R.layout.fragment_plain_player) {
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
plainPlaybackControlsFragment.hide()
|
plainPlaybackControlsFragment.hide()
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toolbarIconColor() = colorControlNormal()
|
override fun toolbarIconColor() = colorControlNormal()
|
||||||
|
|
|
@ -71,10 +71,6 @@ class SimplePlayerFragment : AbsPlayerFragment(R.layout.fragment_simple_player)
|
||||||
controlsFragment.hide()
|
controlsFragment.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor() = colorControlNormal()
|
override fun toolbarIconColor() = colorControlNormal()
|
||||||
|
|
||||||
override fun onColorChanged(color: MediaNotificationProcessor) {
|
override fun onColorChanged(color: MediaNotificationProcessor) {
|
||||||
|
|
|
@ -62,10 +62,6 @@ class TinyPlayerFragment : AbsPlayerFragment(R.layout.fragment_tiny_player),
|
||||||
|
|
||||||
override fun onHide() {}
|
override fun onHide() {}
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toolbarIconColor(): Int {
|
override fun toolbarIconColor(): Int {
|
||||||
return toolbarColor
|
return toolbarColor
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ import com.google.android.material.transition.MaterialArcMotion
|
||||||
import com.google.android.material.transition.MaterialContainerTransform
|
import com.google.android.material.transition.MaterialContainerTransform
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator
|
import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator
|
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
|
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
@ -126,15 +125,11 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
||||||
val wrappedAdapter: RecyclerView.Adapter<*> =
|
val wrappedAdapter: RecyclerView.Adapter<*> =
|
||||||
dragDropManager.createWrappedAdapter(playlistSongAdapter)
|
dragDropManager.createWrappedAdapter(playlistSongAdapter)
|
||||||
|
|
||||||
|
|
||||||
val animator: GeneralItemAnimator = DraggableItemAnimator()
|
|
||||||
binding.recyclerView.itemAnimator = animator
|
|
||||||
|
|
||||||
dragDropManager.attachRecyclerView(binding.recyclerView)
|
|
||||||
|
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
|
adapter = wrappedAdapter
|
||||||
layoutManager = LinearLayoutManager(requireContext())
|
layoutManager = LinearLayoutManager(requireContext())
|
||||||
binding.recyclerView.adapter = wrappedAdapter
|
itemAnimator = DraggableItemAnimator()
|
||||||
|
dragDropManager.attachRecyclerView(this)
|
||||||
ThemedFastScroller.create(this)
|
ThemedFastScroller.create(this)
|
||||||
}
|
}
|
||||||
playlistSongAdapter.registerAdapterDataObserver(object :
|
playlistSongAdapter.registerAdapterDataObserver(object :
|
||||||
|
|
|
@ -18,7 +18,6 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||||
import code.name.monkey.retromusic.db.SongEntity
|
import code.name.monkey.retromusic.db.SongEntity
|
||||||
import code.name.monkey.retromusic.model.Playlist
|
|
||||||
import code.name.monkey.retromusic.repository.RealRepository
|
import code.name.monkey.retromusic.repository.RealRepository
|
||||||
|
|
||||||
class PlaylistDetailsViewModel(
|
class PlaylistDetailsViewModel(
|
||||||
|
|
|
@ -20,7 +20,6 @@ import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.MenuCompat
|
import androidx.core.view.MenuCompat
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import code.name.monkey.retromusic.EXTRA_PLAYLIST
|
|
||||||
import code.name.monkey.retromusic.EXTRA_PLAYLIST_ID
|
import code.name.monkey.retromusic.EXTRA_PLAYLIST_ID
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
|
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
|
||||||
|
|
|
@ -80,9 +80,6 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
||||||
recyclerViewDragDropManager = RecyclerViewDragDropManager()
|
recyclerViewDragDropManager = RecyclerViewDragDropManager()
|
||||||
recyclerViewSwipeManager = RecyclerViewSwipeManager()
|
recyclerViewSwipeManager = RecyclerViewSwipeManager()
|
||||||
|
|
||||||
val animator = DraggableItemAnimator()
|
|
||||||
animator.supportsChangeAnimations = false
|
|
||||||
|
|
||||||
playingQueueAdapter = PlayingQueueAdapter(
|
playingQueueAdapter = PlayingQueueAdapter(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
MusicPlayerRemote.playingQueue.toMutableList(),
|
MusicPlayerRemote.playingQueue.toMutableList(),
|
||||||
|
@ -94,12 +91,15 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
||||||
|
|
||||||
linearLayoutManager = LinearLayoutManager(requireContext())
|
linearLayoutManager = LinearLayoutManager(requireContext())
|
||||||
|
|
||||||
binding.recyclerView.layoutManager = linearLayoutManager
|
|
||||||
binding.recyclerView.adapter = wrappedAdapter
|
binding.recyclerView.apply {
|
||||||
binding.recyclerView.itemAnimator = animator
|
layoutManager = linearLayoutManager
|
||||||
recyclerViewTouchActionGuardManager?.attachRecyclerView(binding.recyclerView)
|
adapter = wrappedAdapter
|
||||||
recyclerViewDragDropManager?.attachRecyclerView(binding.recyclerView)
|
itemAnimator = DraggableItemAnimator()
|
||||||
recyclerViewSwipeManager?.attachRecyclerView(binding.recyclerView)
|
recyclerViewTouchActionGuardManager?.attachRecyclerView(this)
|
||||||
|
recyclerViewDragDropManager?.attachRecyclerView(this)
|
||||||
|
recyclerViewSwipeManager?.attachRecyclerView(this)
|
||||||
|
}
|
||||||
linearLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
|
linearLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
|
||||||
|
|
||||||
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
|
@ -184,6 +184,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
||||||
|
binding.appBarLayout.toolbar.isTitleCentered = false
|
||||||
binding.clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor())
|
binding.clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor())
|
||||||
ColorStateList.valueOf(
|
ColorStateList.valueOf(
|
||||||
MaterialValueHelper.getPrimaryTextColor(
|
MaterialValueHelper.getPrimaryTextColor(
|
||||||
|
|
|
@ -49,11 +49,16 @@ class AudioSettings : AbsSettingsFragment() {
|
||||||
if (VersionUtils.hasS()) {
|
if (VersionUtils.hasS()) {
|
||||||
bluetoothPreference?.setOnPreferenceChangeListener { _, newValue ->
|
bluetoothPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
if (newValue as Boolean) {
|
if (newValue as Boolean) {
|
||||||
if (ActivityCompat.checkSelfPermission(requireContext(),
|
if (ActivityCompat.checkSelfPermission(
|
||||||
BLUETOOTH_CONNECT) != PERMISSION_GRANTED
|
requireContext(),
|
||||||
|
BLUETOOTH_CONNECT
|
||||||
|
) != PERMISSION_GRANTED
|
||||||
) {
|
) {
|
||||||
ActivityCompat.requestPermissions(requireActivity(), arrayOf(
|
ActivityCompat.requestPermissions(
|
||||||
BLUETOOTH_CONNECT), BLUETOOTH_PERMISSION_REQUEST)
|
requireActivity(), arrayOf(
|
||||||
|
BLUETOOTH_CONNECT
|
||||||
|
), BLUETOOTH_PERMISSION_REQUEST
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return@setOnPreferenceChangeListener true
|
return@setOnPreferenceChangeListener true
|
||||||
|
|
|
@ -16,6 +16,8 @@ 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.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.core.os.LocaleListCompat
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference
|
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference
|
||||||
import code.name.monkey.retromusic.LANGUAGE_NAME
|
import code.name.monkey.retromusic.LANGUAGE_NAME
|
||||||
|
@ -24,6 +26,7 @@ import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.extensions.installLanguageAndRecreate
|
import code.name.monkey.retromusic.extensions.installLanguageAndRecreate
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
import code.name.monkey.retromusic.fragments.ReloadType.HomeSections
|
import code.name.monkey.retromusic.fragments.ReloadType.HomeSections
|
||||||
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import org.koin.androidx.viewmodel.ext.android.activityViewModel
|
import org.koin.androidx.viewmodel.ext.android.activityViewModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,6 +45,8 @@ class OtherSettingsFragment : AbsSettingsFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
PreferenceUtil.languageCode =
|
||||||
|
AppCompatDelegate.getApplicationLocales().toLanguageTags().ifEmpty { "auto" }
|
||||||
addPreferencesFromResource(R.xml.pref_advanced)
|
addPreferencesFromResource(R.xml.pref_advanced)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +61,18 @@ class OtherSettingsFragment : AbsSettingsFragment() {
|
||||||
val languagePreference: Preference? = findPreference(LANGUAGE_NAME)
|
val languagePreference: Preference? = findPreference(LANGUAGE_NAME)
|
||||||
languagePreference?.setOnPreferenceChangeListener { prefs, newValue ->
|
languagePreference?.setOnPreferenceChangeListener { prefs, newValue ->
|
||||||
setSummary(prefs, newValue)
|
setSummary(prefs, newValue)
|
||||||
requireActivity().installLanguageAndRecreate(newValue.toString())
|
if (newValue as? String == "auto") {
|
||||||
|
AppCompatDelegate.setApplicationLocales(LocaleListCompat.getEmptyLocaleList())
|
||||||
|
} else {
|
||||||
|
// Install the languages from Play Store first and then set the application locale
|
||||||
|
requireActivity().installLanguageAndRecreate(newValue.toString()) {
|
||||||
|
AppCompatDelegate.setApplicationLocales(
|
||||||
|
LocaleListCompat.forLanguageTags(
|
||||||
|
newValue as? String
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,22 +17,27 @@ package code.name.monkey.retromusic.fragments.settings
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference
|
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference
|
||||||
import code.name.monkey.retromusic.APPBAR_MODE
|
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference
|
||||||
import code.name.monkey.retromusic.HOME_ALBUM_GRID_STYLE
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.HOME_ARTIST_GRID_STYLE
|
import code.name.monkey.retromusic.*
|
||||||
import code.name.monkey.retromusic.R
|
|
||||||
import code.name.monkey.retromusic.TAB_TEXT_MODE
|
|
||||||
|
|
||||||
class PersonalizeSettingsFragment : AbsSettingsFragment() {
|
class PersonalizeSettingsFragment : AbsSettingsFragment() {
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
addPreferencesFromResource(R.xml.pref_ui)
|
addPreferencesFromResource(R.xml.pref_ui)
|
||||||
|
// Hide Blur album art preference on Android 11+ devices as the lockscreen album art feature was removed by Google
|
||||||
|
// And if the feature is present in some Custom ROM's there is also an option to set blur so this preference is unnecessary on Android 11 and above
|
||||||
|
val blurredAlbumArt: ATESwitchPreference? = findPreference(BLURRED_ALBUM_ART)
|
||||||
|
blurredAlbumArt?.isVisible = !VersionUtils.hasR()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invalidateSettings() {}
|
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 albumArtOnLockscreen: ATESwitchPreference? = findPreference(ALBUM_ART_ON_LOCK_SCREEN)
|
||||||
|
albumArtOnLockscreen?.isVisible = !VersionUtils.hasT()
|
||||||
|
|
||||||
val homeArtistStyle: ATEListPreference? = findPreference(HOME_ARTIST_GRID_STYLE)
|
val homeArtistStyle: ATEListPreference? = findPreference(HOME_ARTIST_GRID_STYLE)
|
||||||
homeArtistStyle?.setOnPreferenceChangeListener { preference, newValue ->
|
homeArtistStyle?.setOnPreferenceChangeListener { preference, newValue ->
|
||||||
setSummary(preference, newValue)
|
setSummary(preference, newValue)
|
||||||
|
|
|
@ -24,7 +24,6 @@ import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
||||||
import code.name.monkey.retromusic.databinding.FragmentSettingsBinding
|
import code.name.monkey.retromusic.databinding.FragmentSettingsBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyToolbar
|
|
||||||
import code.name.monkey.retromusic.extensions.findNavController
|
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
|
||||||
|
|
|
@ -139,5 +139,7 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
addPreferencesFromResource(R.xml.pref_general)
|
addPreferencesFromResource(R.xml.pref_general)
|
||||||
|
val wallpaperAccent: ATESwitchPreference? = findPreference(WALLPAPER_ACCENT)
|
||||||
|
wallpaperAccent?.isVisible = VersionUtils.hasOreoMR1() && !VersionUtils.hasS()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,11 @@ import java.io.InputStream
|
||||||
@GlideModule
|
@GlideModule
|
||||||
class RetroMusicGlideModule : AppGlideModule() {
|
class RetroMusicGlideModule : AppGlideModule() {
|
||||||
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
||||||
registry.prepend(PlaylistPreview::class.java, Bitmap::class.java, PlaylistPreviewLoader.Factory(context))
|
registry.prepend(
|
||||||
|
PlaylistPreview::class.java,
|
||||||
|
Bitmap::class.java,
|
||||||
|
PlaylistPreviewLoader.Factory(context)
|
||||||
|
)
|
||||||
registry.prepend(
|
registry.prepend(
|
||||||
AudioFileCover::class.java,
|
AudioFileCover::class.java,
|
||||||
InputStream::class.java,
|
InputStream::class.java,
|
||||||
|
|
|
@ -17,7 +17,6 @@ package code.name.monkey.retromusic.glide
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.retromusic.R
|
|
||||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTarget
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTarget
|
||||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||||
import code.name.monkey.retromusic.util.ColorUtil
|
import code.name.monkey.retromusic.util.ColorUtil
|
||||||
|
|
|
@ -2,21 +2,27 @@ package code.name.monkey.retromusic.service
|
||||||
|
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Context
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
|
import android.provider.Settings
|
||||||
import androidx.core.animation.doOnEnd
|
import androidx.core.animation.doOnEnd
|
||||||
import code.name.monkey.retromusic.service.playback.Playback
|
import code.name.monkey.retromusic.service.playback.Playback
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
|
|
||||||
class AudioFader {
|
class AudioFader {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun createFadeAnimator(
|
fun createFadeAnimator(
|
||||||
|
context: Context,
|
||||||
fadeInMp: MediaPlayer,
|
fadeInMp: MediaPlayer,
|
||||||
fadeOutMp: MediaPlayer,
|
fadeOutMp: MediaPlayer,
|
||||||
endAction: (animator: Animator) -> Unit, /* Code to run when Animator Ends*/
|
endAction: (animator: Animator) -> Unit, /* Code to run when Animator Ends*/
|
||||||
): Animator? {
|
): Animator? {
|
||||||
val duration = PreferenceUtil.crossFadeDuration * 1000
|
// Get Global animator scale
|
||||||
if (duration == 0) {
|
val animScale = Settings.Global.getFloat(context.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f)
|
||||||
|
|
||||||
|
// Set duration according to the global animation scale, so cross-fade actually lasts for the duration set by the user
|
||||||
|
val duration = (PreferenceUtil.crossFadeDuration * 1000 ) / animScale
|
||||||
|
if (duration == 0F) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return ValueAnimator.ofFloat(0f, 1f).apply {
|
return ValueAnimator.ofFloat(0f, 1f).apply {
|
||||||
|
|
|
@ -34,6 +34,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||||
private var durationListener = DurationListener()
|
private var durationListener = DurationListener()
|
||||||
private var mIsInitialized = false
|
private var mIsInitialized = false
|
||||||
private var hasDataSource: Boolean = false /* Whether first player has DataSource */
|
private var hasDataSource: Boolean = false /* Whether first player has DataSource */
|
||||||
|
private var nextDataSource:String? = null
|
||||||
private var crossFadeAnimator: Animator? = null
|
private var crossFadeAnimator: Animator? = null
|
||||||
override var callbacks: PlaybackCallbacks? = null
|
override var callbacks: PlaybackCallbacks? = null
|
||||||
private var crossFadeDuration = PreferenceUtil.crossFadeDuration
|
private var crossFadeDuration = PreferenceUtil.crossFadeDuration
|
||||||
|
@ -92,8 +93,10 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun seek(whereto: Int): Int {
|
override fun seek(whereto: Int, force: Boolean): Int {
|
||||||
endFade()
|
if (force) {
|
||||||
|
endFade()
|
||||||
|
}
|
||||||
getNextPlayer()?.stop()
|
getNextPlayer()?.stop()
|
||||||
return try {
|
return try {
|
||||||
getCurrentPlayer()?.seekTo(whereto)
|
getCurrentPlayer()?.seekTo(whereto)
|
||||||
|
@ -143,7 +146,12 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNextDataSource(path: String?) {}
|
override fun setNextDataSource(path: String?) {
|
||||||
|
// Store the next song path in nextDataSource, we'll need this just in case
|
||||||
|
// if the user closes the app, then we can't get the nextSong from musicService
|
||||||
|
// As MusicPlayerRemote won't have access to the musicService
|
||||||
|
nextDataSource = path
|
||||||
|
}
|
||||||
|
|
||||||
override fun setAudioSessionId(sessionId: Int): Boolean {
|
override fun setAudioSessionId(sessionId: Int): Boolean {
|
||||||
return try {
|
return try {
|
||||||
|
@ -228,7 +236,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||||
|
|
||||||
private fun crossFade(fadeInMp: MediaPlayer, fadeOutMp: MediaPlayer) {
|
private fun crossFade(fadeInMp: MediaPlayer, fadeOutMp: MediaPlayer) {
|
||||||
isCrossFading = true
|
isCrossFading = true
|
||||||
crossFadeAnimator = createFadeAnimator(fadeInMp, fadeOutMp) {
|
crossFadeAnimator = createFadeAnimator(context, fadeInMp, fadeOutMp) {
|
||||||
crossFadeAnimator = null
|
crossFadeAnimator = null
|
||||||
durationListener.start()
|
durationListener.start()
|
||||||
isCrossFading = false
|
isCrossFading = false
|
||||||
|
@ -281,7 +289,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||||
fun start() {
|
fun start() {
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
job = launch {
|
job = launch {
|
||||||
while (true) {
|
while (isActive) {
|
||||||
delay(250)
|
delay(250)
|
||||||
onDurationUpdated(position(), duration())
|
onDurationUpdated(position(), duration())
|
||||||
}
|
}
|
||||||
|
@ -298,10 +306,21 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||||
getNextPlayer()?.let { player ->
|
getNextPlayer()?.let { player ->
|
||||||
val nextSong = MusicPlayerRemote.nextSong
|
val nextSong = MusicPlayerRemote.nextSong
|
||||||
// Switch to other player (Crossfade) only if next song exists
|
// Switch to other player (Crossfade) only if next song exists
|
||||||
if (nextSong != null) {
|
// If we get an empty song it's can be because the app was cleared from background
|
||||||
|
// And MusicPlayerRemote don't have access to MusicService
|
||||||
|
if (nextSong != null && nextSong != Song.emptySong) {
|
||||||
|
nextDataSource = null
|
||||||
setDataSourceImpl(player, nextSong.uri.toString()) { success ->
|
setDataSourceImpl(player, nextSong.uri.toString()) { success ->
|
||||||
if (success) switchPlayer()
|
if (success) switchPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// So we have to use the previously stored nextDataSource value
|
||||||
|
else if (!nextDataSource.isNullOrEmpty()) {
|
||||||
|
setDataSourceImpl(player, nextDataSource!!) { success ->
|
||||||
|
if (success) switchPlayer()
|
||||||
|
nextDataSource = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,7 +354,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun crossFadeScope(): CoroutineScope = CoroutineScope(Job() + Dispatchers.Main)
|
internal fun crossFadeScope(): CoroutineScope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
|
|
||||||
fun MediaPlayer.setPlaybackSpeedPitch(speed: Float, pitch: Float) {
|
fun MediaPlayer.setPlaybackSpeedPitch(speed: Float, pitch: Float) {
|
||||||
if (hasMarshmallow()) {
|
if (hasMarshmallow()) {
|
||||||
|
|
|
@ -200,7 +200,7 @@ class MultiPlayer(context: Context) : LocalPlayback(context) {
|
||||||
* @param whereto The offset in milliseconds from the start to seek to
|
* @param whereto The offset in milliseconds from the start to seek to
|
||||||
* @return The offset in milliseconds from the start to seek to
|
* @return The offset in milliseconds from the start to seek to
|
||||||
*/
|
*/
|
||||||
override fun seek(whereto: Int): Int {
|
override fun seek(whereto: Int, force: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
mCurrentMediaPlayer.seekTo(whereto)
|
mCurrentMediaPlayer.seekTo(whereto)
|
||||||
whereto
|
whereto
|
||||||
|
|
|
@ -38,10 +38,10 @@ import android.support.v4.media.session.PlaybackStateCompat
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.app.ServiceCompat
|
import androidx.core.app.ServiceCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.os.BundleCompat
|
import androidx.core.os.BundleCompat
|
||||||
import androidx.core.os.ParcelCompat
|
|
||||||
import androidx.media.MediaBrowserServiceCompat
|
import androidx.media.MediaBrowserServiceCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
|
@ -50,12 +50,10 @@ import code.name.monkey.retromusic.activities.LockScreenActivity
|
||||||
import code.name.monkey.retromusic.appwidgets.*
|
import code.name.monkey.retromusic.appwidgets.*
|
||||||
import code.name.monkey.retromusic.auto.AutoMediaIDHelper
|
import code.name.monkey.retromusic.auto.AutoMediaIDHelper
|
||||||
import code.name.monkey.retromusic.auto.AutoMusicProvider
|
import code.name.monkey.retromusic.auto.AutoMusicProvider
|
||||||
import code.name.monkey.retromusic.extensions.extra
|
|
||||||
import code.name.monkey.retromusic.extensions.showToast
|
import code.name.monkey.retromusic.extensions.showToast
|
||||||
import code.name.monkey.retromusic.extensions.toMediaSessionQueue
|
import code.name.monkey.retromusic.extensions.toMediaSessionQueue
|
||||||
import code.name.monkey.retromusic.extensions.uri
|
import code.name.monkey.retromusic.extensions.uri
|
||||||
import code.name.monkey.retromusic.glide.BlurTransformation
|
import code.name.monkey.retromusic.glide.BlurTransformation
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension.getDefaultTransition
|
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension.getSongModel
|
import code.name.monkey.retromusic.glide.RetroGlideExtension.getSongModel
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
|
import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
|
||||||
import code.name.monkey.retromusic.helper.ShuffleHelper.makeShuffleList
|
import code.name.monkey.retromusic.helper.ShuffleHelper.makeShuffleList
|
||||||
|
@ -289,8 +287,8 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
setupMediaSession()
|
setupMediaSession()
|
||||||
|
|
||||||
uiThreadHandler = Handler(Looper.getMainLooper())
|
uiThreadHandler = Handler(Looper.getMainLooper())
|
||||||
registerReceiver(widgetIntentReceiver, IntentFilter(APP_WIDGET_UPDATE))
|
ContextCompat.registerReceiver(this, widgetIntentReceiver, IntentFilter(APP_WIDGET_UPDATE), ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
registerReceiver(updateFavoriteReceiver, IntentFilter(FAVORITE_STATE_CHANGED))
|
ContextCompat.registerReceiver(this, updateFavoriteReceiver, IntentFilter(FAVORITE_STATE_CHANGED), ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||||
registerReceiver(lockScreenReceiver, IntentFilter(Intent.ACTION_SCREEN_ON))
|
registerReceiver(lockScreenReceiver, IntentFilter(Intent.ACTION_SCREEN_ON))
|
||||||
sessionToken = mediaSession?.sessionToken
|
sessionToken = mediaSession?.sessionToken
|
||||||
notificationManager = getSystemService()
|
notificationManager = getSystemService()
|
||||||
|
@ -706,7 +704,7 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
|| repeatMode == REPEAT_MODE_NONE && isLastTrack
|
|| repeatMode == REPEAT_MODE_NONE && isLastTrack
|
||||||
) {
|
) {
|
||||||
notifyChange(PLAY_STATE_CHANGED)
|
notifyChange(PLAY_STATE_CHANGED)
|
||||||
seek(0)
|
seek(0, false)
|
||||||
if (pendingQuit) {
|
if (pendingQuit) {
|
||||||
pendingQuit = false
|
pendingQuit = false
|
||||||
quit()
|
quit()
|
||||||
|
@ -726,7 +724,7 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
if (pendingQuit || repeatMode == REPEAT_MODE_NONE && isLastTrack) {
|
if (pendingQuit || repeatMode == REPEAT_MODE_NONE && isLastTrack) {
|
||||||
playbackManager.setNextDataSource(null)
|
playbackManager.setNextDataSource(null)
|
||||||
pause(false)
|
pause(false)
|
||||||
seek(0)
|
seek(0, false)
|
||||||
if (pendingQuit) {
|
if (pendingQuit) {
|
||||||
pendingQuit = false
|
pendingQuit = false
|
||||||
quit()
|
quit()
|
||||||
|
@ -973,9 +971,9 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun seek(millis: Int): Int {
|
fun seek(millis: Int, force: Boolean = true): Int {
|
||||||
return try {
|
return try {
|
||||||
val newPosition = playbackManager.seek(millis)
|
val newPosition = playbackManager.seek(millis, force)
|
||||||
throttledSeekHandler?.notifySeek()
|
throttledSeekHandler?.notifySeek()
|
||||||
newPosition
|
newPosition
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -1048,7 +1046,9 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, null)
|
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, null)
|
||||||
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, playingQueue.size.toLong())
|
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, playingQueue.size.toLong())
|
||||||
|
|
||||||
if (isAlbumArtOnLockScreen) {
|
// We must send the album art in METADATA_KEY_ALBUM_ART key on A13+ or
|
||||||
|
// else album art is blurry in notification
|
||||||
|
if (isAlbumArtOnLockScreen || VersionUtils.hasT()) {
|
||||||
// val screenSize: Point = RetroUtil.getScreenSize(this)
|
// val screenSize: Point = RetroUtil.getScreenSize(this)
|
||||||
val request = Glide.with(this)
|
val request = Glide.with(this)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
|
|
|
@ -78,7 +78,7 @@ class PlaybackManager(val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun seek(millis: Int): Int = playback!!.seek(millis)
|
fun seek(millis: Int, force: Boolean): Int = playback!!.seek(millis, force)
|
||||||
|
|
||||||
fun setDataSource(
|
fun setDataSource(
|
||||||
song: Song,
|
song: Song,
|
||||||
|
|
|
@ -45,7 +45,7 @@ interface Playback {
|
||||||
|
|
||||||
fun position(): Int
|
fun position(): Int
|
||||||
|
|
||||||
fun seek(whereto: Int): Int
|
fun seek(whereto: Int, force: Boolean): Int
|
||||||
|
|
||||||
fun setVolume(vol: Float): Boolean
|
fun setVolume(vol: Float): Boolean
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.Locale
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class CustomArtistImageUtil private constructor(context: Context) {
|
class CustomArtistImageUtil private constructor(context: Context) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import android.content.Intent
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import code.name.monkey.retromusic.BuildConfig
|
import code.name.monkey.retromusic.BuildConfig
|
||||||
import code.name.monkey.retromusic.extensions.showToast
|
import code.name.monkey.retromusic.extensions.showToast
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,20 @@ object PreferenceUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val languageCode: String get() = sharedPreferences.getString(LANGUAGE_NAME, "auto") ?: "auto"
|
var languageCode: String
|
||||||
|
get() = sharedPreferences.getString(LANGUAGE_NAME, "auto") ?: "auto"
|
||||||
|
set(value) = sharedPreferences.edit {
|
||||||
|
putString(LANGUAGE_NAME, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var isLocaleAutoStorageEnabled: Boolean
|
||||||
|
get() = sharedPreferences.getBoolean(
|
||||||
|
LOCALE_AUTO_STORE_ENABLED,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
set(value) = sharedPreferences.edit {
|
||||||
|
putBoolean(LOCALE_AUTO_STORE_ENABLED, value)
|
||||||
|
}
|
||||||
|
|
||||||
var Fragment.userName
|
var Fragment.userName
|
||||||
get() = sharedPreferences.getString(
|
get() = sharedPreferences.getString(
|
||||||
|
@ -266,11 +279,6 @@ object PreferenceUtil {
|
||||||
ALBUM_ART_ON_LOCK_SCREEN, true
|
ALBUM_ART_ON_LOCK_SCREEN, true
|
||||||
)
|
)
|
||||||
|
|
||||||
val isAudioDucking
|
|
||||||
get() = sharedPreferences.getBoolean(
|
|
||||||
AUDIO_DUCKING, true
|
|
||||||
)
|
|
||||||
|
|
||||||
val isBluetoothSpeaker
|
val isBluetoothSpeaker
|
||||||
get() = sharedPreferences.getBoolean(
|
get() = sharedPreferences.getBoolean(
|
||||||
BLUETOOTH_PLAYBACK, false
|
BLUETOOTH_PLAYBACK, false
|
||||||
|
@ -279,7 +287,7 @@ object PreferenceUtil {
|
||||||
val isBlurredAlbumArt
|
val isBlurredAlbumArt
|
||||||
get() = sharedPreferences.getBoolean(
|
get() = sharedPreferences.getBoolean(
|
||||||
BLURRED_ALBUM_ART, false
|
BLURRED_ALBUM_ART, false
|
||||||
)
|
) && !VersionUtils.hasR()
|
||||||
|
|
||||||
val blurAmount get() = sharedPreferences.getInt(NEW_BLUR_AMOUNT, 25)
|
val blurAmount get() = sharedPreferences.getInt(NEW_BLUR_AMOUNT, 25)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import code.name.monkey.retromusic.databinding.CollapsingAppbarLayoutBinding
|
import code.name.monkey.retromusic.databinding.CollapsingAppbarLayoutBinding
|
||||||
import code.name.monkey.retromusic.databinding.SimpleAppbarLayoutBinding
|
import code.name.monkey.retromusic.databinding.SimpleAppbarLayoutBinding
|
||||||
|
|
|
@ -13,17 +13,16 @@
|
||||||
-->
|
-->
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
<code.name.monkey.retromusic.views.TopAppBarLayout
|
<code.name.monkey.retromusic.views.TopAppBarLayout
|
||||||
android:id="@+id/appBarLayout"
|
android:id="@+id/appBarLayout"
|
||||||
|
style="?appBarLayoutStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true" />
|
||||||
app:liftOnScroll="true" />
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
android:id="@+id/container"
|
android:id="@+id/container"
|
||||||
|
|
|
@ -44,18 +44,19 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
app:cardCornerRadius="6dp"
|
app:cardCornerRadius="8dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
app:shapeAppearance="@style/ShapeAppearance.Material3.Corner.Small"
|
||||||
tools:srcCompat="@tools:sample/backgrounds/scenic"
|
tools:srcCompat="@tools:sample/backgrounds/scenic"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
@ -93,6 +94,7 @@
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
|
@ -35,18 +35,19 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
app:cardCornerRadius="10dp"
|
app:cardCornerRadius="8dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
android:layout_width="45dp"
|
android:layout_width="45dp"
|
||||||
android:layout_height="45dp"
|
android:layout_height="45dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
app:shapeAppearance="?shapeAppearanceCornerSmall"
|
||||||
tools:srcCompat="@tools:sample/backgrounds/scenic"
|
tools:srcCompat="@tools:sample/backgrounds/scenic"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
android:textAppearance="@style/TextViewBody2"
|
android:textAppearance="@style/TextViewBody2"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
@ -4,14 +4,15 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:background="?rectSelector"
|
android:background="?rectSelector"
|
||||||
android:transitionGroup="true">
|
android:clickable="true"
|
||||||
|
android:focusable="true">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/dummy_view"
|
android:id="@+id/dummy_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_gravity="center_vertical|start"
|
android:layout_gravity="center_vertical|start"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -34,7 +36,6 @@
|
||||||
app:srcCompat="@drawable/ic_drag_handle"
|
app:srcCompat="@drawable/ic_drag_handle"
|
||||||
app:tint="?attr/colorControlNormal"
|
app:tint="?attr/colorControlNormal"
|
||||||
tools:ignore="ContentDescription"
|
tools:ignore="ContentDescription"
|
||||||
android:paddingHorizontal="8dp"
|
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,18 +44,20 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
app:cardCornerRadius="6dp"
|
android:transitionGroup="true"
|
||||||
|
app:cardCornerRadius="4dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
app:shapeAppearance="@style/ShapeAppearance.Material3.Corner.ExtraSmall"
|
||||||
tools:srcCompat="@tools:sample/backgrounds/scenic"
|
tools:srcCompat="@tools:sample/backgrounds/scenic"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
@ -94,6 +97,7 @@
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<bool name="isNotOreo">false</bool>
|
|
||||||
</resources>
|
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<bool name="wallpaper_accent_visible">true</bool>
|
|
||||||
</resources>
|
|
|
@ -2,6 +2,4 @@
|
||||||
<resources>
|
<resources>
|
||||||
<bool name="md3_available">true</bool>
|
<bool name="md3_available">true</bool>
|
||||||
<bool name="md3_enabled">true</bool>
|
<bool name="md3_enabled">true</bool>
|
||||||
|
|
||||||
<bool name="wallpaper_accent_visible">false</bool>
|
|
||||||
</resources>
|
</resources>
|
|
@ -5,9 +5,5 @@
|
||||||
|
|
||||||
<bool name="allowBackup">true</bool>
|
<bool name="allowBackup">true</bool>
|
||||||
|
|
||||||
<bool name="wallpaper_accent_enabled">false</bool>
|
|
||||||
<bool name="wallpaper_accent_visible">false</bool>
|
|
||||||
|
|
||||||
<bool name="isNotOreo">true</bool>
|
|
||||||
<bool name="isMarshmallow">false</bool>
|
<bool name="isMarshmallow">false</bool>
|
||||||
</resources>
|
</resources>
|
|
@ -562,4 +562,5 @@
|
||||||
<string name="you_have_to_select_at_least_one_category">You have to select at least one category.</string>
|
<string name="you_have_to_select_at_least_one_category">You have to select at least one category.</string>
|
||||||
<string name="you_will_be_forwarded_to_the_issue_tracker_website">You will be forwarded to the issue tracker website.</string>
|
<string name="you_will_be_forwarded_to_the_issue_tracker_website">You will be forwarded to the issue tracker website.</string>
|
||||||
<string name="your_account_data_is_only_used_for_authentication">Your account data is only used for authentication.</string>
|
<string name="your_account_data_is_only_used_for_authentication">Your account data is only used for authentication.</string>
|
||||||
|
<string name="could_not_write_tags_to_file">Could not write tags to the music file!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
45
app/src/main/res/xml/locales_config.xml
Normal file
45
app/src/main/res/xml/locales_config.xml
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<locale android:name="en" />
|
||||||
|
<locale android:name="ar-SA" />
|
||||||
|
<locale android:name="eu-ES" />
|
||||||
|
<locale android:name="my-MM" />
|
||||||
|
<locale android:name="zh-CN" />
|
||||||
|
<locale android:name="zh-HK" />
|
||||||
|
<locale android:name="zh-TW" />
|
||||||
|
<locale android:name="hr" />
|
||||||
|
<locale android:name="cs-cz" />
|
||||||
|
<locale android:name="da-DK" />
|
||||||
|
<locale android:name="nl-NL" />
|
||||||
|
<locale android:name="en" />
|
||||||
|
<locale android:name="fil-PH" />
|
||||||
|
<locale android:name="fr" />
|
||||||
|
<locale android:name="de" />
|
||||||
|
<locale android:name="el" />
|
||||||
|
<locale android:name="hi" />
|
||||||
|
<locale android:name="hu" />
|
||||||
|
<locale android:name="in" />
|
||||||
|
<locale android:name="it" />
|
||||||
|
<locale android:name="ja" />
|
||||||
|
<locale android:name="kn" />
|
||||||
|
<locale android:name="ko" />
|
||||||
|
<locale android:name="kmr-TR" />
|
||||||
|
<locale android:name="lv-LV" />
|
||||||
|
<locale android:name="ml" />
|
||||||
|
<locale android:name="fa" />
|
||||||
|
<locale android:name="pl" />
|
||||||
|
<locale android:name="pt-BR" />
|
||||||
|
<locale android:name="pt-PT" />
|
||||||
|
<locale android:name="ro" />
|
||||||
|
<locale android:name="ru" />
|
||||||
|
<locale android:name="sr" />
|
||||||
|
<locale android:name="es" />
|
||||||
|
<locale android:name="es-419" />
|
||||||
|
<locale android:name="sv" />
|
||||||
|
<locale android:name="ta" />
|
||||||
|
<locale android:name="te" />
|
||||||
|
<locale android:name="th-TH" />
|
||||||
|
<locale android:name="tr" />
|
||||||
|
<locale android:name="uk" />
|
||||||
|
<locale android:name="vi" />
|
||||||
|
</locale-config>
|
|
@ -2,15 +2,6 @@
|
||||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="audio_ducking"
|
|
||||||
android:layout="@layout/list_item_view_switch"
|
|
||||||
android:summary="@string/pref_summary_audio_ducking"
|
|
||||||
android:title="@string/pref_title_audio_ducking"
|
|
||||||
app:icon="@drawable/ic_volume_down"
|
|
||||||
app:isPreferenceVisible="@bool/isNotOreo"/>
|
|
||||||
|
|
||||||
<code.name.monkey.retromusic.preferences.DurationPreference
|
<code.name.monkey.retromusic.preferences.DurationPreference
|
||||||
android:defaultValue="0"
|
android:defaultValue="0"
|
||||||
android:key="audio_fade_duration"
|
android:key="audio_fade_duration"
|
||||||
|
|
|
@ -43,12 +43,11 @@
|
||||||
android:title="@string/colors">
|
android:title="@string/colors">
|
||||||
|
|
||||||
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference
|
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference
|
||||||
android:defaultValue="@bool/wallpaper_accent_enabled"
|
android:defaultValue="false"
|
||||||
android:key="wallpaper_accent"
|
android:key="wallpaper_accent"
|
||||||
android:layout="@layout/list_item_view_switch"
|
android:layout="@layout/list_item_view_switch"
|
||||||
android:summary="@string/pref_summary_wallpaper_accent"
|
android:summary="@string/pref_summary_wallpaper_accent"
|
||||||
android:title="@string/pref_title_wallpaper_accent"
|
android:title="@string/pref_title_wallpaper_accent" />
|
||||||
app:isPreferenceVisible="@bool/wallpaper_accent_visible" />
|
|
||||||
|
|
||||||
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATEColorPreference
|
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATEColorPreference
|
||||||
android:dependency="material_you"
|
android:dependency="material_you"
|
||||||
|
|
|
@ -12,20 +12,22 @@ import com.google.android.play.core.splitinstall.SplitInstallManagerFactory
|
||||||
import com.google.android.play.core.splitinstall.SplitInstallRequest
|
import com.google.android.play.core.splitinstall.SplitInstallRequest
|
||||||
import com.google.android.play.core.splitinstall.SplitInstallSessionState
|
import com.google.android.play.core.splitinstall.SplitInstallSessionState
|
||||||
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
|
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
|
||||||
|
import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun Context.setUpMediaRouteButton(menu: Menu) {
|
fun Context.setUpMediaRouteButton(menu: Menu) {
|
||||||
CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.action_cast)
|
CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.action_cast)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FragmentActivity.installLanguageAndRecreate(code: String) {
|
fun FragmentActivity.installLanguageAndRecreate(code: String, onInstallComplete: () -> Unit) {
|
||||||
var mySessionId = 0
|
var mySessionId = 0
|
||||||
|
|
||||||
val manager = SplitInstallManagerFactory.create(this)
|
val manager = SplitInstallManagerFactory.create(this)
|
||||||
val listener = object: SplitInstallStateUpdatedListener{
|
val listener = object: SplitInstallStateUpdatedListener{
|
||||||
override fun onStateUpdate(state: SplitInstallSessionState) {
|
override fun onStateUpdate(state: SplitInstallSessionState) {
|
||||||
if (state.sessionId() == mySessionId) {
|
// Restart the activity if the language is installed (sessionId is same and status is installed)
|
||||||
recreate()
|
if (state.sessionId() == mySessionId && state.status() == SplitInstallSessionStatus.INSTALLED) {
|
||||||
|
onInstallComplete()
|
||||||
manager.unregisterListener(this)
|
manager.unregisterListener(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ class CastPlayer(castSession: CastSession) : Playback, RemoteMediaClient.Callbac
|
||||||
return remoteMediaClient?.approximateStreamPosition?.toInt() ?: 0
|
return remoteMediaClient?.approximateStreamPosition?.toInt() ?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun seek(whereto: Int): Int {
|
override fun seek(whereto: Int, force: Boolean): Int {
|
||||||
remoteMediaClient?.seek(MediaSeekOptions.Builder().setPosition(whereto.toLong()).build())
|
remoteMediaClient?.seek(MediaSeekOptions.Builder().setPosition(whereto.toLong()).build())
|
||||||
return whereto
|
return whereto
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
android {
|
android {
|
||||||
compileSdk 32
|
compileSdk 33
|
||||||
namespace "code.name.monkey.appthemehelper"
|
namespace "code.name.monkey.appthemehelper"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 21
|
minSdk 21
|
||||||
targetSdk 32
|
targetSdk 33
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
|
|
|
@ -82,4 +82,13 @@ object VersionUtils {
|
||||||
fun hasS(): Boolean {
|
fun hasS(): Boolean {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if device is running API >= 33
|
||||||
|
*/
|
||||||
|
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
|
||||||
|
@JvmStatic
|
||||||
|
fun hasT(): Boolean {
|
||||||
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
lifecycle_version = '2.6.0'
|
lifecycle_version = '2.6.1'
|
||||||
navigation_version = '2.5.3'
|
navigation_version = '2.5.3'
|
||||||
mdc_version = '1.9.0-alpha02'
|
mdc_version = '1.9.0-beta01'
|
||||||
preference_version = '1.2.0'
|
preference_version = '1.2.0'
|
||||||
appcompat_version = '1.6.1'
|
appcompat_version = '1.6.1'
|
||||||
core_version = '1.10.0-rc01'
|
core_version = '1.10.0-rc01'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue