Merge pull request #592 from naveensingh/sdk_and_viewbinding_migration

Migrate to View binding, SDK 34 and Version catalogs
This commit is contained in:
Tibor Kaputa 2023-09-05 14:27:07 +02:00 committed by GitHub
commit afc92bf21c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 1361 additions and 1235 deletions

View file

@ -1,93 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.simplemobiletools.musicplayer"
minSdkVersion 23
targetSdkVersion 33
versionCode 114
versionName "5.17.1"
setProperty("archivesBaseName", "music-player")
vectorDrawables.useSupportLibrary = true
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
}
}
}
flavorDimensions "variants"
productFlavors {
core {}
fdroid {}
prepaid {}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
coreLibraryDesugaringEnabled = true
}
}
dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:f76d729b9d'
implementation 'org.greenrobot:eventbus:3.3.1'
implementation 'androidx.media:media:1.6.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-process:2.5.1'
implementation 'androidx.media3:media3-session:1.1.1'
implementation 'androidx.media3:media3-exoplayer:1.1.1'
implementation 'com.google.android.material:material:1.6.1'
implementation 'com.airbnb.android:lottie:3.6.1'
implementation 'com.github.bjoernpetersen:m3u-parser:1.3.0'
implementation 'me.grantland:autofittextview:0.2.1'
coreLibraryDesugaring('com.android.tools:desugar_jdk_libs:1.1.5')
// higher versions of jaudiotagger not compatible with <= API 25 devices
// https://bitbucket.org/ijabz/jaudiotagger/issues/149/some-nio-classes-are-unavailable-while
implementation "net.jthink:jaudiotagger:2.2.5"
kapt "androidx.room:room-compiler:2.5.2"
implementation "androidx.room:room-runtime:2.5.2"
annotationProcessor "androidx.room:room-compiler:2.5.2"
}

109
app/build.gradle.kts Normal file
View file

@ -0,0 +1,109 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.konan.properties.Properties
import java.io.FileInputStream
plugins {
alias(libs.plugins.android)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.ksp)
}
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
compileSdk = project.libs.versions.app.build.compileSDKVersion.get().toInt()
defaultConfig {
applicationId = libs.versions.app.version.appId.get()
minSdk = project.libs.versions.app.build.minimumSDK.get().toInt()
targetSdk = project.libs.versions.app.build.targetSDK.get().toInt()
versionName = project.libs.versions.app.version.versionName.get()
versionCode = project.libs.versions.app.version.versionCode.get().toInt()
setProperty("archivesBaseName", "music-player")
vectorDrawables.useSupportLibrary = true
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
register("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
}
buildFeatures {
viewBinding = true
buildConfig = true
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
}
}
flavorDimensions.add("variants")
productFlavors {
register("core")
register("fdroid")
register("prepaid")
}
sourceSets {
getByName("main").java.srcDirs("src/main/kotlin")
}
compileOptions {
val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString())
sourceCompatibility = currentJavaVersionFromLibs
targetCompatibility = currentJavaVersionFromLibs
isCoreLibraryDesugaringEnabled = true
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
}
namespace = libs.versions.app.version.appId.get()
lint {
checkReleaseBuilds = false
abortOnError = false
}
}
dependencies {
implementation(libs.simple.mobile.tools.commons)
implementation(libs.eventbus)
implementation(libs.androidx.media)
implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.lifecycle.process)
implementation(libs.androidx.media3.session)
implementation(libs.androidx.media3.exoplayer)
implementation(libs.lottie)
implementation(libs.m3u.parser)
implementation(libs.autofittextview)
implementation(libs.jaudiotagger)
coreLibraryDesugaring(libs.desugar.jdk.libs)
implementation(libs.bundles.room)
ksp(libs.androidx.room.compiler)
}

View file

@ -8,15 +8,17 @@
public <fields>;
}
# Gson uses generic type information stored in a class file when working with
# fields. Proguard removes such information by default, keep it.
-keepattributes Signature
# This is also needed for R8 in compat mode since multiple optimizations will
# remove the generic signature such as class merging and argument removal.
-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken
# EventBus
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Picasso
-dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.ConscryptPlatform

View file

@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

View file

@ -10,29 +10,30 @@ import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.adapters.AlbumsTracksAdapter
import com.simplemobiletools.musicplayer.databinding.ActivityAlbumsBinding
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.helpers.ALBUM
import com.simplemobiletools.musicplayer.helpers.ARTIST
import com.simplemobiletools.musicplayer.models.*
import kotlinx.android.synthetic.main.activity_albums.*
import kotlinx.android.synthetic.main.view_current_track_bar.current_track_bar
// Artists -> Albums -> Tracks
class AlbumsActivity : SimpleMusicActivity() {
private val binding by viewBinding(ActivityAlbumsBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_albums)
setContentView(binding.root)
updateMaterialActivityViews(albums_coordinator, albums_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(albums_list, albums_toolbar)
updateMaterialActivityViews(binding.albumsCoordinator, binding.albumsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.albumsList, binding.albumsToolbar)
albums_fastscroller.updateColors(getProperPrimaryColor())
binding.albumsFastscroller.updateColors(getProperPrimaryColor())
val artistType = object : TypeToken<Artist>() {}.type
val artist = Gson().fromJson<Artist>(intent.getStringExtra(ARTIST), artistType)
albums_toolbar.title = artist.title
binding.albumsToolbar.title = artist.title
ensureBackgroundThread {
val albums = audioHelper.getArtistAlbums(artist.id)
@ -50,7 +51,7 @@ class AlbumsActivity : SimpleMusicActivity() {
listItems.addAll(albumTracks)
runOnUiThread {
AlbumsTracksAdapter(this, listItems, albums_list) {
AlbumsTracksAdapter(this, listItems, binding.albumsList) {
hideKeyboard()
if (it is Album) {
Intent(this, TracksActivity::class.java).apply {
@ -63,25 +64,29 @@ class AlbumsActivity : SimpleMusicActivity() {
val startIndex = albumTracks.indexOf(it as Track)
prepareAndPlay(albumTracks, startIndex)
} else {
PermissionRequiredDialog(this, R.string.allow_notifications_music_player, { openNotificationSettings() })
PermissionRequiredDialog(
this,
com.simplemobiletools.commons.R.string.allow_notifications_music_player,
{ openNotificationSettings() }
)
}
}
}
}.apply {
albums_list.adapter = this
binding.albumsList.adapter = this
}
if (areSystemAnimationsEnabled) {
albums_list.scheduleLayoutAnimation()
binding.albumsList.scheduleLayoutAnimation()
}
}
}
setupCurrentTrackBar(current_track_bar)
setupCurrentTrackBar(binding.currentTrackBar.root)
}
override fun onResume() {
super.onResume()
setupToolbar(albums_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.albumsToolbar, NavigationIcon.Arrow)
}
}

View file

@ -12,32 +12,35 @@ import com.simplemobiletools.commons.helpers.DARK_GREY
import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.views.MySeekBar
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ActivityEqualizerBinding
import com.simplemobiletools.musicplayer.databinding.EqualizerBandBinding
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.helpers.EQUALIZER_PRESET_CUSTOM
import com.simplemobiletools.musicplayer.playback.SimpleEqualizer
import kotlinx.android.synthetic.main.activity_equalizer.*
import kotlinx.android.synthetic.main.equalizer_band.view.*
import java.text.DecimalFormat
import kotlin.math.log10
import kotlin.math.pow
import kotlin.math.roundToInt
class EqualizerActivity : SimpleActivity() {
private var bands = HashMap<Short, Int>()
private var bandSeekBars = ArrayList<MySeekBar>()
private val binding by viewBinding(ActivityEqualizerBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_equalizer)
setContentView(binding.root)
updateMaterialActivityViews(equalizer_coordinator, equalizer_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(equalizer_nested_scrollview, equalizer_toolbar)
updateMaterialActivityViews(binding.equalizerCoordinator, binding.equalizerHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.equalizerNestedScrollview, binding.equalizerToolbar)
initMediaPlayer()
}
override fun onResume() {
super.onResume()
setupToolbar(equalizer_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.equalizerToolbar, NavigationIcon.Arrow)
}
@SuppressLint("SetTextI18n")
@ -52,46 +55,46 @@ class EqualizerActivity : SimpleActivity() {
setupBands(equalizer)
setupPresets(equalizer)
updateTextColors(equalizer_holder)
updateTextColors(binding.equalizerHolder)
val presetTextColor = if (isWhiteTheme()) {
DARK_GREY
} else {
getProperPrimaryColor().getContrastColor()
}
equalizer_preset.setTextColor(presetTextColor)
binding.equalizerPreset.setTextColor(presetTextColor)
}
@SuppressLint("SetTextI18n")
private fun setupBands(equalizer: Equalizer) {
val minValue = equalizer.bandLevelRange[0]
val maxValue = equalizer.bandLevelRange[1]
equalizer_label_right.text = "+${maxValue / 100}"
equalizer_label_left.text = "${minValue / 100}"
equalizer_label_0.text = (minValue + maxValue).toString()
binding.equalizerLabelRight.text = "+${maxValue / 100}"
binding.equalizerLabelLeft.text = "${minValue / 100}"
binding.equalizerLabel0.text = (minValue + maxValue).toString()
bandSeekBars.clear()
equalizer_bands_holder.removeAllViews()
binding.equalizerBandsHolder.removeAllViews()
val bandType = object : TypeToken<HashMap<Short, Int>>() {}.type
bands = Gson().fromJson<HashMap<Short, Int>>(config.equalizerBands, bandType) ?: HashMap()
for (band in 0 until equalizer.numberOfBands) {
val frequency = equalizer.getCenterFreq(band.toShort()) / 1000
val frequency = equalizer.getCenterFreq(band.toShort()) / 1000.0
val formatted = formatFrequency(frequency)
layoutInflater.inflate(R.layout.equalizer_band, equalizer_bands_holder, false).apply {
equalizer_bands_holder.addView(this)
bandSeekBars.add(this.equalizer_band_seek_bar)
this.equalizer_band_label.text = formatted
this.equalizer_band_label.setTextColor(getProperTextColor())
this.equalizer_band_seek_bar.max = maxValue - minValue
EqualizerBandBinding.inflate(layoutInflater, binding.equalizerBandsHolder, false).apply {
binding.equalizerBandsHolder.addView(root)
bandSeekBars.add(equalizerBandSeekBar)
equalizerBandLabel.text = formatted
equalizerBandLabel.setTextColor(getProperTextColor())
equalizerBandSeekBar.max = maxValue - minValue
this.equalizer_band_seek_bar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
equalizerBandSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
val newProgress = (progress / 100.0).roundToInt() * 100
this@apply.equalizer_band_seek_bar.progress = newProgress
equalizerBandSeekBar.progress = newProgress
val newValue = newProgress + minValue
try {
@ -109,7 +112,7 @@ class EqualizerActivity : SimpleActivity() {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
bands[band.toShort()] = this@apply.equalizer_band_seek_bar.progress
bands[band.toShort()] = equalizerBandSeekBar.progress
config.equalizerBands = Gson().toJson(bands)
}
})
@ -118,7 +121,7 @@ class EqualizerActivity : SimpleActivity() {
}
private fun draggingStarted(equalizer: Equalizer) {
equalizer_preset.text = getString(R.string.custom)
binding.equalizerPreset.text = getString(com.simplemobiletools.commons.R.string.custom)
config.equalizerPreset = EQUALIZER_PRESET_CUSTOM
for (band in 0 until equalizer.numberOfBands) {
bands[band.toShort()] = bandSeekBars[band].progress
@ -133,13 +136,13 @@ class EqualizerActivity : SimpleActivity() {
config.equalizerPreset = EQUALIZER_PRESET_CUSTOM
}
equalizer_preset.setOnClickListener {
binding.equalizerPreset.setOnClickListener {
val items = arrayListOf<RadioItem>()
(0 until equalizer.numberOfPresets).mapTo(items) {
RadioItem(it, equalizer.getPresetName(it.toShort()))
}
items.add(RadioItem(EQUALIZER_PRESET_CUSTOM, getString(R.string.custom)))
items.add(RadioItem(EQUALIZER_PRESET_CUSTOM, getString(com.simplemobiletools.commons.R.string.custom)))
RadioGroupDialog(this, items, config.equalizerPreset) { presetId ->
try {
config.equalizerPreset = presetId as Int
@ -154,7 +157,7 @@ class EqualizerActivity : SimpleActivity() {
private fun presetChanged(presetId: Int, equalizer: Equalizer) {
if (presetId == EQUALIZER_PRESET_CUSTOM) {
equalizer_preset.text = getString(R.string.custom)
binding.equalizerPreset.text = getString(com.simplemobiletools.commons.R.string.custom)
for (band in 0 until equalizer.numberOfBands) {
val minValue = equalizer.bandLevelRange[0]
@ -173,9 +176,9 @@ class EqualizerActivity : SimpleActivity() {
val presetName = equalizer.getPresetName(presetId.toShort())
if (presetName.isEmpty()) {
config.equalizerPreset = EQUALIZER_PRESET_CUSTOM
equalizer_preset.text = getString(R.string.custom)
binding.equalizerPreset.text = getString(com.simplemobiletools.commons.R.string.custom)
} else {
equalizer_preset.text = presetName
binding.equalizerPreset.text = presetName
}
equalizer.usePreset(presetId.toShort())
@ -188,14 +191,14 @@ class EqualizerActivity : SimpleActivity() {
}
}
// copypasted from the file size formatter, should be simplified
private fun formatFrequency(value: Int): String {
// copy-pasted from the file size formatter, should be simplified
private fun formatFrequency(value: Double): String {
if (value <= 0) {
return "0 Hz"
}
val units = arrayOf("Hz", "kHz", "gHz")
val digitGroups = (Math.log10(value.toDouble()) / Math.log10(1000.0)).toInt()
return "${DecimalFormat("#,##0.#").format(value / Math.pow(1000.0, digitGroups.toDouble()))} ${units[digitGroups]}"
val digitGroups = (log10(value) / log10(1000.0)).toInt()
return "${DecimalFormat("#,##0.#").format(value / 1000.0.pow(digitGroups.toDouble()))} ${units[digitGroups]}"
}
}

View file

@ -3,38 +3,41 @@ package com.simplemobiletools.musicplayer.activities
import android.os.Bundle
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.adapters.ExcludedFoldersAdapter
import com.simplemobiletools.musicplayer.databinding.ActivityExcludedFoldersBinding
import com.simplemobiletools.musicplayer.extensions.config
import kotlinx.android.synthetic.main.activity_excluded_folders.*
class ExcludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
private val binding by viewBinding(ActivityExcludedFoldersBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_excluded_folders)
setContentView(binding.root)
updateMaterialActivityViews(excluded_folders_coordinator, excluded_folders_list, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(excluded_folders_list, excluded_folders_toolbar)
updateMaterialActivityViews(binding.excludedFoldersCoordinator, binding.excludedFoldersList, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.excludedFoldersList, binding.excludedFoldersToolbar)
updateFolders()
}
override fun onResume() {
super.onResume()
setupToolbar(excluded_folders_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.excludedFoldersToolbar, NavigationIcon.Arrow)
}
private fun updateFolders() {
val folders = config.excludedFolders.toMutableList() as ArrayList<String>
excluded_folders_placeholder.apply {
binding.excludedFoldersPlaceholder.apply {
beVisibleIf(folders.isEmpty())
setTextColor(getProperTextColor())
}
val adapter = ExcludedFoldersAdapter(this, folders, this, excluded_folders_list) {}
excluded_folders_list.adapter = adapter
val adapter = ExcludedFoldersAdapter(this, folders, this, binding.excludedFoldersList) {}
binding.excludedFoldersList.adapter = adapter
}
override fun refreshItems() {

View file

@ -8,10 +8,9 @@ import android.graphics.drawable.Drawable
import android.media.AudioManager
import android.net.Uri
import android.os.Bundle
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.commons.databinding.BottomTablayoutItemBinding
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
@ -22,23 +21,16 @@ import com.simplemobiletools.commons.models.Release
import com.simplemobiletools.musicplayer.BuildConfig
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.adapters.ViewPagerAdapter
import com.simplemobiletools.musicplayer.databinding.ActivityMainBinding
import com.simplemobiletools.musicplayer.dialogs.NewPlaylistDialog
import com.simplemobiletools.musicplayer.dialogs.SelectPlaylistDialog
import com.simplemobiletools.musicplayer.dialogs.SleepTimerCustomDialog
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.fragments.MyViewPagerFragment
import com.simplemobiletools.musicplayer.fragments.PlaylistsFragment
import com.simplemobiletools.musicplayer.helpers.*
import com.simplemobiletools.musicplayer.helpers.M3uImporter.ImportResult
import com.simplemobiletools.musicplayer.models.Events
import com.simplemobiletools.musicplayer.playback.CustomCommands
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_albums.albums_fragment_holder
import kotlinx.android.synthetic.main.fragment_artists.artists_fragment_holder
import kotlinx.android.synthetic.main.fragment_folders.folders_fragment_holder
import kotlinx.android.synthetic.main.fragment_genres.genres_fragment_holder
import kotlinx.android.synthetic.main.fragment_playlists.playlists_fragment_holder
import kotlinx.android.synthetic.main.fragment_tracks.tracks_fragment_holder
import kotlinx.android.synthetic.main.view_current_track_bar.current_track_bar
import me.grantland.widget.AutofitHelper
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
@ -52,22 +44,25 @@ class MainActivity : SimpleMusicActivity() {
private var storedShowTabs = 0
private var storedExcludedFolders = 0
private val binding by viewBinding(ActivityMainBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentView(binding.root)
appLaunched(BuildConfig.APPLICATION_ID)
setupOptionsMenu()
refreshMenuItems()
updateMaterialActivityViews(main_coordinator, main_holder, useTransparentNavigation = false, useTopSearchMenu = true)
updateMaterialActivityViews(binding.mainCoordinator, binding.mainHolder, useTransparentNavigation = false, useTopSearchMenu = true)
storeStateVariables()
setupTabs()
setupCurrentTrackBar(binding.currentTrackBar.root)
handlePermission(getPermissionToRequest()) {
if (it) {
initActivity()
} else {
toast(R.string.no_storage_permissions)
toast(com.simplemobiletools.commons.R.string.no_storage_permissions)
finish()
}
}
@ -75,14 +70,6 @@ class MainActivity : SimpleMusicActivity() {
volumeControlStream = AudioManager.STREAM_MUSIC
checkWhatsNewDialog()
checkAppOnSDCard()
withPlayer {
maybePreparePlayer(context = this@MainActivity) { success ->
if (success) {
updateCurrentTrackBar()
broadcastUpdateWidgetState()
}
}
}
}
override fun onResume() {
@ -94,17 +81,17 @@ class MainActivity : SimpleMusicActivity() {
}
updateMenuColors()
updateTextColors(main_holder)
updateTextColors(binding.mainHolder)
setupTabColors()
val properTextColor = getProperTextColor()
val properPrimaryColor = getProperPrimaryColor()
sleep_timer_holder.background = ColorDrawable(getProperBackgroundColor())
sleep_timer_stop.applyColorFilter(properTextColor)
loading_progress_bar.setIndicatorColor(properPrimaryColor)
loading_progress_bar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA)
binding.sleepTimerHolder.background = ColorDrawable(getProperBackgroundColor())
binding.sleepTimerStop.applyColorFilter(properTextColor)
binding.loadingProgressBar.setIndicatorColor(properPrimaryColor)
binding.loadingProgressBar.trackColor = properPrimaryColor.adjustAlpha(LOWER_ALPHA)
getAllFragments().forEach {
it?.setupColors(properTextColor, properPrimaryColor)
it.setupColors(properTextColor, properPrimaryColor)
}
if (storedExcludedFolders != config.excludedFolders.hashCode()) {
@ -115,7 +102,7 @@ class MainActivity : SimpleMusicActivity() {
override fun onPause() {
super.onPause()
storeStateVariables()
config.lastUsedViewPagerPage = view_pager.currentItem
config.lastUsedViewPagerPage = binding.viewPager.currentItem
}
override fun onDestroy() {
@ -124,38 +111,39 @@ class MainActivity : SimpleMusicActivity() {
}
override fun onBackPressed() {
if (main_menu.isSearchOpen) {
main_menu.closeSearch()
if (binding.mainMenu.isSearchOpen) {
binding.mainMenu.closeSearch()
} else {
super.onBackPressed()
}
}
private fun refreshMenuItems() {
main_menu.getToolbar().menu.apply {
findItem(R.id.create_new_playlist).isVisible = getCurrentFragment() == playlists_fragment_holder
findItem(R.id.create_playlist_from_folder).isVisible = getCurrentFragment() == playlists_fragment_holder
findItem(R.id.import_playlist).isVisible = getCurrentFragment() == playlists_fragment_holder && isOreoPlus()
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
binding.mainMenu.getToolbar().menu.apply {
val isPlaylistFragment = getCurrentFragment() is PlaylistsFragment
findItem(R.id.create_new_playlist).isVisible = isPlaylistFragment
findItem(R.id.create_playlist_from_folder).isVisible = isPlaylistFragment
findItem(R.id.import_playlist).isVisible = isPlaylistFragment && isOreoPlus()
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)
}
}
private fun setupOptionsMenu() {
main_menu.getToolbar().inflateMenu(R.menu.menu_main)
main_menu.toggleHideOnScroll(false)
main_menu.setupMenu()
binding.mainMenu.getToolbar().inflateMenu(R.menu.menu_main)
binding.mainMenu.toggleHideOnScroll(false)
binding.mainMenu.setupMenu()
main_menu.onSearchClosedListener = {
binding.mainMenu.onSearchClosedListener = {
getAllFragments().forEach {
it?.onSearchClosed()
it.onSearchClosed()
}
}
main_menu.onSearchTextChangedListener = { text ->
binding.mainMenu.onSearchTextChangedListener = { text ->
getCurrentFragment()?.onSearchQueryChanged(text)
}
main_menu.getToolbar().setOnMenuItemClickListener { menuItem ->
binding.mainMenu.getToolbar().setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.sort -> showSortingDialog()
R.id.rescan_media -> refreshAllFragments(showProgress = true)
@ -175,7 +163,7 @@ class MainActivity : SimpleMusicActivity() {
private fun updateMenuColors() {
updateStatusbarColor(getProperBackgroundColor())
main_menu.updateColors()
binding.mainMenu.updateColors()
}
private fun storeStateVariables() {
@ -191,28 +179,31 @@ class MainActivity : SimpleMusicActivity() {
// trigger a scan first so that the fragments will accurately reflect the scanning state
mediaScanner.scan()
initFragments()
sleep_timer_stop.setOnClickListener { stopSleepTimer() }
binding.sleepTimerStop.setOnClickListener { stopSleepTimer() }
setupCurrentTrackBar(current_track_bar)
refreshAllFragments()
}
private fun refreshAllFragments(showProgress: Boolean = config.appRunCount == 1) {
if (showProgress) {
loading_progress_bar.show()
binding.loadingProgressBar.show()
}
handleNotificationPermission { granted ->
mediaScanner.scan(progress = showProgress && granted) { complete ->
runOnUiThread {
getAllFragments().forEach {
it?.setupFragment(this)
it.setupFragment(this)
}
if (complete) {
loading_progress_bar.hide()
binding.loadingProgressBar.hide()
withPlayer {
sendCommand(CustomCommands.RELOAD_CONTENT)
if (currentMediaItem == null) {
maybePreparePlayer()
} else {
sendCommand(CustomCommands.RELOAD_CONTENT)
}
}
}
}
@ -221,62 +212,61 @@ class MainActivity : SimpleMusicActivity() {
}
private fun initFragments() {
view_pager.adapter = ViewPagerAdapter(this)
view_pager.offscreenPageLimit = tabsList.size - 1
view_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
binding.viewPager.adapter = ViewPagerAdapter(this)
binding.viewPager.offscreenPageLimit = tabsList.size - 1
binding.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
main_tabs_holder.getTabAt(position)?.select()
binding.mainTabsHolder.getTabAt(position)?.select()
getAllFragments().forEach {
it?.finishActMode()
it.finishActMode()
}
refreshMenuItems()
}
})
view_pager.currentItem = config.lastUsedViewPagerPage
binding.viewPager.currentItem = config.lastUsedViewPagerPage
}
private fun setupTabs() {
main_tabs_holder.removeAllTabs()
tabsList.forEachIndexed { index, value ->
if (config.showTabs and value != 0) {
main_tabs_holder.newTab().setCustomView(R.layout.bottom_tablayout_item).apply {
customView?.findViewById<ImageView>(R.id.tab_item_icon)?.setImageDrawable(getTabIcon(value))
customView?.findViewById<TextView>(R.id.tab_item_label)?.text = getTabLabel(value)
AutofitHelper.create(customView?.findViewById(R.id.tab_item_label))
main_tabs_holder.addTab(this)
}
binding.mainTabsHolder.removeAllTabs()
getVisibleTabs().forEach { value ->
binding.mainTabsHolder.newTab().setCustomView(com.simplemobiletools.commons.R.layout.bottom_tablayout_item).apply {
val tabItemBinding = BottomTablayoutItemBinding.bind(customView!!)
tabItemBinding.tabItemIcon.setImageDrawable(getTabIcon(value))
tabItemBinding.tabItemLabel.text = getTabLabel(value)
AutofitHelper.create(tabItemBinding.tabItemLabel)
binding.mainTabsHolder.addTab(this)
}
}
main_tabs_holder.onTabSelectionChanged(
binding.mainTabsHolder.onTabSelectionChanged(
tabUnselectedAction = {
updateBottomTabItemColors(it.customView, false)
},
tabSelectedAction = {
main_menu.closeSearch()
view_pager.currentItem = it.position
binding.mainMenu.closeSearch()
binding.viewPager.currentItem = it.position
updateBottomTabItemColors(it.customView, true)
}
)
main_tabs_holder.beGoneIf(main_tabs_holder.tabCount == 1)
binding.mainTabsHolder.beGoneIf(binding.mainTabsHolder.tabCount == 1)
}
private fun setupTabColors() {
val activeView = main_tabs_holder.getTabAt(view_pager.currentItem)?.customView
val activeView = binding.mainTabsHolder.getTabAt(binding.viewPager.currentItem)?.customView
updateBottomTabItemColors(activeView, true)
getInactiveTabIndexes(view_pager.currentItem).forEach { index ->
val inactiveView = main_tabs_holder.getTabAt(index)?.customView
getInactiveTabIndexes(binding.viewPager.currentItem).forEach { index ->
val inactiveView = binding.mainTabsHolder.getTabAt(index)?.customView
updateBottomTabItemColors(inactiveView, false)
}
val bottomBarColor = getBottomNavigationBackgroundColor()
main_tabs_holder.setBackgroundColor(bottomBarColor)
binding.mainTabsHolder.setBackgroundColor(bottomBarColor)
updateNavigationBarColor(bottomBarColor)
}
@ -286,7 +276,7 @@ class MainActivity : SimpleMusicActivity() {
val drawableId = when (position) {
TAB_PLAYLISTS -> R.drawable.ic_playlist_vector
TAB_FOLDERS -> R.drawable.ic_folders_vector
TAB_ARTISTS -> R.drawable.ic_person_vector
TAB_ARTISTS -> com.simplemobiletools.commons.R.drawable.ic_person_vector
TAB_ALBUMS -> R.drawable.ic_album_vector
TAB_GENRES -> R.drawable.ic_genre_vector
else -> R.drawable.ic_music_note_vector
@ -308,36 +298,6 @@ class MainActivity : SimpleMusicActivity() {
return resources.getString(stringId)
}
private fun getCurrentFragment(): MyViewPagerFragment? {
val showTabs = config.showTabs
val fragments = arrayListOf<MyViewPagerFragment>()
if (showTabs and TAB_PLAYLISTS != 0) {
fragments.add(playlists_fragment_holder)
}
if (showTabs and TAB_FOLDERS != 0) {
fragments.add(folders_fragment_holder)
}
if (showTabs and TAB_ARTISTS != 0) {
fragments.add(artists_fragment_holder)
}
if (showTabs and TAB_ALBUMS != 0) {
fragments.add(albums_fragment_holder)
}
if (showTabs and TAB_TRACKS != 0) {
fragments.add(tracks_fragment_holder)
}
if (showTabs and TAB_GENRES != 0) {
fragments.add(genres_fragment_holder)
}
return fragments.getOrNull(view_pager.currentItem)
}
private fun showSortingDialog() {
getCurrentFragment()?.onSortOpen(this)
}
@ -386,7 +346,7 @@ class MainActivity : SimpleMusicActivity() {
uri.scheme == "content" -> {
val tempFile = getTempFile("imports", uri.path!!.getFilenameFromPath())
if (tempFile == null) {
toast(R.string.unknown_error_occurred)
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
return
}
@ -401,7 +361,7 @@ class MainActivity : SimpleMusicActivity() {
}
}
else -> toast(R.string.invalid_file_format)
else -> toast(com.simplemobiletools.commons.R.string.invalid_file_format)
}
}
@ -415,7 +375,7 @@ class MainActivity : SimpleMusicActivity() {
try {
startActivityForResult(this, PICK_IMPORT_SOURCE_INTENT)
} catch (e: ActivityNotFoundException) {
toast(R.string.system_service_disabled, Toast.LENGTH_LONG)
toast(com.simplemobiletools.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
showErrorToast(e)
}
@ -449,21 +409,21 @@ class MainActivity : SimpleMusicActivity() {
runOnUiThread {
toast(
when (result) {
ImportResult.IMPORT_OK -> R.string.importing_successful
ImportResult.IMPORT_PARTIAL -> R.string.importing_some_entries_failed
else -> R.string.importing_failed
ImportResult.IMPORT_OK -> com.simplemobiletools.commons.R.string.importing_successful
ImportResult.IMPORT_PARTIAL -> com.simplemobiletools.commons.R.string.importing_some_entries_failed
else -> com.simplemobiletools.commons.R.string.importing_failed
}
)
playlists_fragment_holder.setupFragment(this)
getAdapter()?.getPlaylistsFragment()?.setupFragment(this)
}
}.importPlaylist(path, id)
}
}
private fun showSleepTimer() {
val minutes = getString(R.string.minutes_raw)
val hour = resources.getQuantityString(R.plurals.hours, 1, 1)
val minutes = getString(com.simplemobiletools.commons.R.string.minutes_raw)
val hour = resources.getQuantityString(com.simplemobiletools.commons.R.plurals.hours, 1, 1)
val items = arrayListOf(
RadioItem(5 * 60, "5 $minutes"),
@ -475,12 +435,12 @@ class MainActivity : SimpleMusicActivity() {
if (items.none { it.id == config.lastSleepTimerSeconds }) {
val lastSleepTimerMinutes = config.lastSleepTimerSeconds / 60
val text = resources.getQuantityString(R.plurals.minutes, lastSleepTimerMinutes, lastSleepTimerMinutes)
val text = resources.getQuantityString(com.simplemobiletools.commons.R.plurals.minutes, lastSleepTimerMinutes, lastSleepTimerMinutes)
items.add(RadioItem(config.lastSleepTimerSeconds, text))
}
items.sortBy { it.id }
items.add(RadioItem(-1, getString(R.string.custom)))
items.add(RadioItem(-1, getString(com.simplemobiletools.commons.R.string.custom)))
RadioGroupDialog(this, items, config.lastSleepTimerSeconds) {
if (it as Int == -1) {
@ -502,32 +462,29 @@ class MainActivity : SimpleMusicActivity() {
}
private fun startSleepTimer() {
sleep_timer_holder.fadeIn()
binding.sleepTimerHolder.fadeIn()
withPlayer {
sendCommand(CustomCommands.TOGGLE_SLEEP_TIMER)
}
}
private fun stopSleepTimer() {
sleep_timer_holder.fadeOut()
binding.sleepTimerHolder.fadeOut()
withPlayer {
sendCommand(CustomCommands.TOGGLE_SLEEP_TIMER)
}
}
private fun getAllFragments() = arrayListOf(
playlists_fragment_holder,
folders_fragment_holder,
artists_fragment_holder,
albums_fragment_holder,
tracks_fragment_holder,
genres_fragment_holder
)
private fun getAdapter() = binding.viewPager.adapter as? ViewPagerAdapter
private fun getAllFragments() = getAdapter()?.getAllFragments().orEmpty()
private fun getCurrentFragment() = getAdapter()?.getCurrentFragment()
@Subscribe(threadMode = ThreadMode.MAIN)
fun sleepTimerChanged(event: Events.SleepTimerChanged) {
sleep_timer_value.text = event.seconds.getFormattedDuration()
sleep_timer_holder.beVisible()
binding.sleepTimerValue.text = event.seconds.getFormattedDuration()
binding.sleepTimerHolder.beVisible()
if (event.seconds == 0) {
finish()
@ -536,12 +493,12 @@ class MainActivity : SimpleMusicActivity() {
@Subscribe(threadMode = ThreadMode.MAIN)
fun playlistsUpdated(event: Events.PlaylistsUpdated) {
playlists_fragment_holder?.setupFragment(this)
getAdapter()?.getPlaylistsFragment()?.setupFragment(this)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun tracksUpdated(event: Events.RefreshTracks) {
tracks_fragment_holder?.setupFragment(this)
getAdapter()?.getTracksFragment()?.setupFragment(this)
}
@Subscribe(threadMode = ThreadMode.MAIN)
@ -564,14 +521,14 @@ class MainActivity : SimpleMusicActivity() {
val faqItems = arrayListOf(
FAQItem(R.string.faq_1_title, R.string.faq_1_text),
FAQItem(R.string.faq_1_title_commons, R.string.faq_1_text_commons),
FAQItem(R.string.faq_4_title_commons, R.string.faq_4_text_commons),
FAQItem(R.string.faq_9_title_commons, R.string.faq_9_text_commons)
FAQItem(com.simplemobiletools.commons.R.string.faq_1_title_commons, com.simplemobiletools.commons.R.string.faq_1_text_commons),
FAQItem(com.simplemobiletools.commons.R.string.faq_4_title_commons, com.simplemobiletools.commons.R.string.faq_4_text_commons),
FAQItem(com.simplemobiletools.commons.R.string.faq_9_title_commons, com.simplemobiletools.commons.R.string.faq_9_text_commons)
)
if (!resources.getBoolean(R.bool.hide_google_relations)) {
faqItems.add(FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons))
faqItems.add(FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons))
if (!resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)) {
faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_2_title_commons, com.simplemobiletools.commons.R.string.faq_2_text_commons))
faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_6_title_commons, com.simplemobiletools.commons.R.string.faq_6_text_commons))
}
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)

View file

@ -8,40 +8,42 @@ import android.view.MenuItem
import androidx.appcompat.widget.SearchView
import androidx.core.view.MenuItemCompat
import androidx.media3.common.MediaItem
import androidx.media3.common.Timeline
import com.simplemobiletools.commons.extensions.areSystemAnimationsEnabled
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.adapters.QueueAdapter
import com.simplemobiletools.musicplayer.databinding.ActivityQueueBinding
import com.simplemobiletools.musicplayer.dialogs.NewPlaylistDialog
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.helpers.RoomHelper
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.activity_queue.*
class QueueActivity : SimpleControllerActivity() {
private var searchMenuItem: MenuItem? = null
private var isSearchOpen = false
private var tracksIgnoringSearch = ArrayList<Track>()
private val binding by viewBinding(ActivityQueueBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_queue)
setContentView(binding.root)
setupOptionsMenu()
updateMaterialActivityViews(queue_coordinator, queue_list, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(queue_list, queue_toolbar)
updateMaterialActivityViews(binding.queueCoordinator, binding.queueList, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.queueList, binding.queueToolbar)
setupAdapter()
queue_fastscroller.updateColors(getProperPrimaryColor())
binding.queueFastscroller.updateColors(getProperPrimaryColor())
}
override fun onResume() {
super.onResume()
setupToolbar(queue_toolbar, NavigationIcon.Arrow, searchMenuItem = searchMenuItem)
setupToolbar(binding.queueToolbar, NavigationIcon.Arrow, searchMenuItem = searchMenuItem)
}
override fun onBackPressed() {
@ -56,11 +58,9 @@ class QueueActivity : SimpleControllerActivity() {
getAdapter()?.updateCurrentTrack()
}
override fun onTimelineChanged(timeline: Timeline, reason: Int) = updateAdapter()
private fun setupOptionsMenu() {
setupSearch(queue_toolbar.menu)
queue_toolbar.setOnMenuItemClickListener { menuItem ->
setupSearch(binding.queueToolbar.menu)
binding.queueToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.create_playlist_from_queue -> createPlaylistFromQueue()
else -> return@setOnMenuItemClickListener false
@ -111,28 +111,28 @@ class QueueActivity : SimpleControllerActivity() {
private fun onSearchClosed() {
val adapter = getAdapter() ?: return
adapter.updateItems(tracksIgnoringSearch, forceUpdate = true)
queue_placeholder.beGoneIf(tracksIgnoringSearch.isNotEmpty())
binding.queuePlaceholder.beGoneIf(tracksIgnoringSearch.isNotEmpty())
}
private fun onSearchQueryChanged(text: String) {
val filtered = tracksIgnoringSearch.filter { it.title.contains(text, true) }.toMutableList() as ArrayList<Track>
getAdapter()?.updateItems(filtered, text)
queue_placeholder.beGoneIf(filtered.isNotEmpty())
binding.queuePlaceholder.beGoneIf(filtered.isNotEmpty())
}
private fun getAdapter(): QueueAdapter? {
return queue_list.adapter as? QueueAdapter
return binding.queueList.adapter as? QueueAdapter
}
private fun setupAdapter() {
if (getAdapter() == null) {
withPlayer {
val tracks = currentMediaItemsShuffled.toTracks().toMutableList() as ArrayList<Track>
queue_list.adapter = QueueAdapter(
binding.queueList.adapter = QueueAdapter(
activity = this@QueueActivity,
items = tracks,
currentTrack = currentMediaItem?.toTrack(),
recyclerView = queue_list
recyclerView = binding.queueList
) {
withPlayer {
val startIndex = currentMediaItems.indexOfTrack(it as Track)
@ -144,26 +144,17 @@ class QueueActivity : SimpleControllerActivity() {
}
if (areSystemAnimationsEnabled) {
queue_list.scheduleLayoutAnimation()
binding.queueList.scheduleLayoutAnimation()
}
val currentPosition = shuffledMediaItemsIndices.indexOf(currentMediaItemIndex)
if (currentPosition > 0) {
queue_list.lazySmoothScroll(currentPosition)
binding.queueList.lazySmoothScroll(currentPosition)
}
}
}
}
private fun updateAdapter() {
val adapter = getAdapter() ?: return
withPlayer {
val currentTracks = currentMediaItemsShuffled.toTracks() as ArrayList<Track>
adapter.updateItems(currentTracks)
queue_list.lazySmoothScroll(shuffledMediaItemsIndices.indexOf(currentMediaItemIndex))
}
}
private fun createPlaylistFromQueue() {
NewPlaylistDialog(this) { newPlaylistId ->
val tracks = ArrayList<Track>()

View file

@ -10,6 +10,7 @@ import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.commons.helpers.isTiramisuPlus
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ActivitySettingsBinding
import com.simplemobiletools.musicplayer.dialogs.ManageVisibleTabsDialog
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.sendCommand
@ -17,24 +18,25 @@ import com.simplemobiletools.musicplayer.helpers.SHOW_FILENAME_ALWAYS
import com.simplemobiletools.musicplayer.helpers.SHOW_FILENAME_IF_UNAVAILABLE
import com.simplemobiletools.musicplayer.helpers.SHOW_FILENAME_NEVER
import com.simplemobiletools.musicplayer.playback.CustomCommands
import kotlinx.android.synthetic.main.activity_settings.*
import java.util.Locale
import kotlin.system.exitProcess
class SettingsActivity : SimpleControllerActivity() {
private val binding by viewBinding(ActivitySettingsBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
setContentView(binding.root)
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar)
updateMaterialActivityViews(binding.settingsCoordinator, binding.settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.settingsNestedScrollview, binding.settingsToolbar)
}
override fun onResume() {
super.onResume()
setupToolbar(settings_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou()
setupCustomizeColors()
@ -46,29 +48,29 @@ class SettingsActivity : SimpleControllerActivity() {
setupSwapPrevNext()
setupReplaceTitle()
setupGaplessPlayback()
updateTextColors(settings_nested_scrollview)
updateTextColors(binding.settingsNestedScrollview)
arrayOf(settings_color_customization_section_label, settings_general_settings_label, settings_playback_section_label).forEach {
arrayOf(binding.settingsColorCustomizationSectionLabel, binding.settingsGeneralSettingsLabel, binding.settingsPlaybackSectionLabel).forEach {
it.setTextColor(getProperPrimaryColor())
}
}
private fun setupPurchaseThankYou() {
settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled())
settings_purchase_thank_you_holder.setOnClickListener {
private fun setupPurchaseThankYou() = binding.apply {
settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent()
}
}
private fun setupCustomizeColors() {
settings_color_customization_label.text = getCustomizeColorsString()
settings_color_customization_holder.setOnClickListener {
private fun setupCustomizeColors() = binding.apply {
settingsColorCustomizationLabel.text = getCustomizeColorsString()
settingsColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick()
}
}
private fun setupCustomizeWidgetColors() {
settings_widget_color_customization_holder.setOnClickListener {
binding.settingsWidgetColorCustomizationHolder.setOnClickListener {
Intent(this, WidgetConfigureActivity::class.java).apply {
putExtra(IS_CUSTOMIZING_COLORS, true)
startActivity(this)
@ -76,44 +78,44 @@ class SettingsActivity : SimpleControllerActivity() {
}
}
private fun setupUseEnglish() {
settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settings_use_english.isChecked = config.useEnglish
settings_use_english_holder.setOnClickListener {
settings_use_english.toggle()
config.useEnglish = settings_use_english.isChecked
private fun setupUseEnglish() = binding.apply {
settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settingsUseEnglish.isChecked = config.useEnglish
settingsUseEnglishHolder.setOnClickListener {
settingsUseEnglish.toggle()
config.useEnglish = settingsUseEnglish.isChecked
exitProcess(0)
}
}
private fun setupLanguage() {
settings_language.text = Locale.getDefault().displayLanguage
settings_language_holder.beVisibleIf(isTiramisuPlus())
settings_language_holder.setOnClickListener {
private fun setupLanguage() = binding.apply {
settingsLanguage.text = Locale.getDefault().displayLanguage
settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
settingsLanguageHolder.setOnClickListener {
launchChangeAppLanguageIntent()
}
}
private fun setupSwapPrevNext() {
settings_swap_prev_next.isChecked = config.swapPrevNext
settings_swap_prev_next_holder.setOnClickListener {
settings_swap_prev_next.toggle()
config.swapPrevNext = settings_swap_prev_next.isChecked
private fun setupSwapPrevNext() = binding.apply {
settingsSwapPrevNext.isChecked = config.swapPrevNext
settingsSwapPrevNextHolder.setOnClickListener {
settingsSwapPrevNext.toggle()
config.swapPrevNext = settingsSwapPrevNext.isChecked
}
}
private fun setupReplaceTitle() {
settings_show_filename.text = getReplaceTitleText()
settings_show_filename_holder.setOnClickListener {
private fun setupReplaceTitle() = binding.apply {
settingsShowFilename.text = getReplaceTitleText()
settingsShowFilenameHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(SHOW_FILENAME_NEVER, getString(R.string.never)),
RadioItem(SHOW_FILENAME_NEVER, getString(com.simplemobiletools.commons.R.string.never)),
RadioItem(SHOW_FILENAME_IF_UNAVAILABLE, getString(R.string.title_is_not_available)),
RadioItem(SHOW_FILENAME_ALWAYS, getString(R.string.always))
RadioItem(SHOW_FILENAME_ALWAYS, getString(com.simplemobiletools.commons.R.string.always))
)
RadioGroupDialog(this@SettingsActivity, items, config.showFilename) {
config.showFilename = it as Int
settings_show_filename.text = getReplaceTitleText()
settingsShowFilename.text = getReplaceTitleText()
refreshQueueAndTracks()
}
}
@ -121,15 +123,15 @@ class SettingsActivity : SimpleControllerActivity() {
private fun getReplaceTitleText() = getString(
when (config.showFilename) {
SHOW_FILENAME_NEVER -> R.string.never
SHOW_FILENAME_NEVER -> com.simplemobiletools.commons.R.string.never
SHOW_FILENAME_IF_UNAVAILABLE -> R.string.title_is_not_available
else -> R.string.always
else -> com.simplemobiletools.commons.R.string.always
}
)
private fun setupManageShownTabs() {
settings_manage_shown_tabs_holder.setOnClickListener {
ManageVisibleTabsDialog(this) { result ->
private fun setupManageShownTabs() = binding.apply {
settingsManageShownTabsHolder.setOnClickListener {
ManageVisibleTabsDialog(this@SettingsActivity) { result ->
val tabsMask = config.showTabs
if (tabsMask != result) {
config.showTabs = result
@ -142,17 +144,17 @@ class SettingsActivity : SimpleControllerActivity() {
}
private fun setupManageExcludedFolders() {
settings_manage_excluded_folders_holder.beVisibleIf(isQPlus())
settings_manage_excluded_folders_holder.setOnClickListener {
binding.settingsManageExcludedFoldersHolder.beVisibleIf(isQPlus())
binding.settingsManageExcludedFoldersHolder.setOnClickListener {
startActivity(Intent(this, ExcludedFoldersActivity::class.java))
}
}
private fun setupGaplessPlayback() {
settings_gapless_playback.isChecked = config.gaplessPlayback
settings_gapless_playback_holder.setOnClickListener {
settings_gapless_playback.toggle()
config.gaplessPlayback = settings_gapless_playback.isChecked
private fun setupGaplessPlayback() = binding.apply {
settingsGaplessPlayback.isChecked = config.gaplessPlayback
settingsGaplessPlaybackHolder.setOnClickListener {
settingsGaplessPlayback.toggle()
config.gaplessPlayback = settingsGaplessPlayback.isChecked
withPlayer {
sendCommand(CustomCommands.TOGGLE_SKIP_SILENCE)
}

View file

@ -10,7 +10,6 @@ import androidx.media3.session.MediaController
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isRPlus
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.helpers.EXTRA_NEXT_MEDIA_ID
import com.simplemobiletools.musicplayer.helpers.SimpleMediaController
@ -31,6 +30,7 @@ abstract class SimpleControllerActivity : SimpleActivity(), Player.Listener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
controller = SimpleMediaController.getInstance(this)
maybePreparePlayer()
}
override fun onStart() {
@ -43,6 +43,13 @@ abstract class SimpleControllerActivity : SimpleActivity(), Player.Listener {
controller.removeListener(this)
}
override fun onResume() {
super.onResume()
maybePreparePlayer()
}
open fun onPlayerPrepared(success: Boolean) {}
fun withPlayer(callback: MediaController.() -> Unit) = controller.withController(callback)
fun prepareAndPlay(tracks: List<Track>, startIndex: Int = 0, startPositionMs: Long = 0, startActivity: Boolean = true) {
@ -61,6 +68,14 @@ abstract class SimpleControllerActivity : SimpleActivity(), Player.Listener {
}
}
fun maybePreparePlayer() {
withPlayer {
maybePreparePlayer(context = this@SimpleControllerActivity, callback = ::onPlayerPrepared)
}
}
fun togglePlayback() = withPlayer { togglePlayback() }
fun addTracksToQueue(tracks: List<Track>, callback: () -> Unit) {
withPlayer {
val currentMediaItemsIds = currentMediaItems.map { it.mediaId }
@ -117,7 +132,7 @@ abstract class SimpleControllerActivity : SimpleActivity(), Player.Listener {
EventBus.getDefault().post(Events.RefreshFragments())
callback()
} else {
toast(R.string.unknown_error_occurred)
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
}
} else {

View file

@ -7,9 +7,7 @@ import androidx.media3.common.Player
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.extensions.hideKeyboard
import com.simplemobiletools.commons.extensions.openNotificationSettings
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.isReallyPlaying
import com.simplemobiletools.musicplayer.extensions.togglePlayback
import com.simplemobiletools.musicplayer.views.CurrentTrackBar
/**
@ -25,7 +23,7 @@ abstract class SimpleMusicActivity : SimpleControllerActivity(), Player.Listener
fun setupCurrentTrackBar(trackBar: CurrentTrackBar) {
trackBarView = trackBar
trackBarView?.initialize { withPlayer { togglePlayback() } }
trackBarView?.initialize(togglePlayback = ::togglePlayback)
trackBarView?.setOnClickListener {
hideKeyboard()
handleNotificationPermission { granted ->
@ -34,13 +32,13 @@ abstract class SimpleMusicActivity : SimpleControllerActivity(), Player.Listener
startActivity(this)
}
} else {
PermissionRequiredDialog(this, R.string.allow_notifications_music_player, { openNotificationSettings() })
PermissionRequiredDialog(this, com.simplemobiletools.commons.R.string.allow_notifications_music_player, { openNotificationSettings() })
}
}
}
}
fun updateCurrentTrackBar() {
private fun updateCurrentTrackBar() {
trackBarView?.apply {
withPlayer {
updateColors()
@ -50,6 +48,8 @@ abstract class SimpleMusicActivity : SimpleControllerActivity(), Player.Listener
}
}
override fun onPlayerPrepared(success: Boolean) = updateCurrentTrackBar()
@CallSuper
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
trackBarView?.updateCurrentTrack(mediaItem)

View file

@ -25,6 +25,7 @@ import com.bumptech.glide.request.RequestOptions
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.MEDIUM_ALPHA
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ActivityTrackBinding
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.fragments.PlaybackSpeedFragment
import com.simplemobiletools.musicplayer.helpers.*
@ -32,7 +33,6 @@ import com.simplemobiletools.musicplayer.interfaces.PlaybackSpeedListener
import com.simplemobiletools.musicplayer.models.Track
import com.simplemobiletools.musicplayer.playback.CustomCommands
import com.simplemobiletools.musicplayer.playback.PlaybackService
import kotlinx.android.synthetic.main.activity_track.*
import java.text.DecimalFormat
import kotlin.math.min
import kotlin.time.Duration.Companion.milliseconds
@ -46,46 +46,50 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
private val handler = Handler(Looper.getMainLooper())
private val updateIntervalMillis = 500L
private val binding by viewBinding(ActivityTrackBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
showTransparentTop = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_track)
setContentView(binding.root)
nextTrackPlaceholder = resources.getColoredDrawableWithColor(R.drawable.ic_headset, getProperTextColor())
setupButtons()
setupFlingListener()
(activity_track_appbar.layoutParams as ConstraintLayout.LayoutParams).topMargin = statusBarHeight
activity_track_holder.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
activity_track_toolbar.setNavigationOnClickListener {
finish()
}
binding.apply {
(activityTrackAppbar.layoutParams as ConstraintLayout.LayoutParams).topMargin = statusBarHeight
activityTrackHolder.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
activityTrackToolbar.setNavigationOnClickListener {
finish()
}
isThirdPartyIntent = intent.action == Intent.ACTION_VIEW
arrayOf(activity_track_toggle_shuffle, activity_track_previous, activity_track_next, activity_track_playback_setting).forEach {
it.beInvisibleIf(isThirdPartyIntent)
}
isThirdPartyIntent = intent.action == Intent.ACTION_VIEW
arrayOf(activityTrackToggleShuffle, activityTrackPrevious, activityTrackNext, activityTrackPlaybackSetting).forEach {
it.beInvisibleIf(isThirdPartyIntent)
}
if (isThirdPartyIntent) {
initThirdPartyIntent()
return
}
if (isThirdPartyIntent) {
initThirdPartyIntent()
return
}
setupTrackInfo(PlaybackService.currentMediaItem)
setupNextTrackInfo(PlaybackService.nextMediaItem)
activity_track_play_pause.updatePlayPauseIcon(PlaybackService.isPlaying, getProperTextColor())
updatePlayerState()
setupTrackInfo(PlaybackService.currentMediaItem)
setupNextTrackInfo(PlaybackService.nextMediaItem)
activityTrackPlayPause.updatePlayPauseIcon(PlaybackService.isPlaying, getProperTextColor())
updatePlayerState()
next_track_holder.background = ColorDrawable(getProperBackgroundColor())
next_track_holder.setOnClickListener {
startActivity(Intent(applicationContext, QueueActivity::class.java))
nextTrackHolder.background = ColorDrawable(getProperBackgroundColor())
nextTrackHolder.setOnClickListener {
startActivity(Intent(applicationContext, QueueActivity::class.java))
}
}
}
override fun onResume() {
super.onResume()
updateTextColors(activity_track_holder)
activity_track_title.setTextColor(getProperTextColor())
activity_track_artist.setTextColor(getProperTextColor())
updateTextColors(binding.activityTrackHolder)
binding.activityTrackTitle.setTextColor(getProperTextColor())
binding.activityTrackArtist.setTextColor(getProperTextColor())
updatePlayerState()
updateTrackInfo()
}
@ -116,45 +120,52 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
val track = item?.toTrack() ?: return
setupTopArt(track)
activity_track_title.text = track.title
activity_track_artist.text = track.artist
activity_track_title.setOnLongClickListener {
copyToClipboard(activity_track_title.value)
true
}
binding.apply {
activityTrackTitle.text = track.title
activityTrackArtist.text = track.artist
activityTrackTitle.setOnLongClickListener {
copyToClipboard(activityTrackTitle.value)
true
}
activity_track_artist.setOnLongClickListener {
copyToClipboard(activity_track_artist.value)
true
}
activityTrackArtist.setOnLongClickListener {
copyToClipboard(activityTrackArtist.value)
true
}
activity_track_progressbar.max = track.duration
activity_track_progress_max.text = track.duration.getFormattedDuration()
activityTrackProgressbar.max = track.duration
activityTrackProgressMax.text = track.duration.getFormattedDuration()
}
}
private fun initThirdPartyIntent() {
next_track_holder.beGone()
getTrackFromUri(intent.data) {
binding.nextTrackHolder.beGone()
getTrackFromUri(intent.data) { track ->
runOnUiThread {
prepareAndPlay(listOf(it), startActivity = false)
if (track != null) {
prepareAndPlay(listOf(track), startActivity = false)
} else {
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
finish()
}
}
}
}
private fun setupButtons() {
activity_track_toggle_shuffle.setOnClickListener { withPlayer { toggleShuffle() } }
activity_track_previous.setOnClickListener { withPlayer { forceSeekToPrevious() } }
activity_track_play_pause.setOnClickListener { withPlayer { togglePlayback() } }
activity_track_next.setOnClickListener { withPlayer { forceSeekToNext() } }
activity_track_progress_current.setOnClickListener { seekBack() }
activity_track_progress_max.setOnClickListener { seekForward() }
activity_track_playback_setting.setOnClickListener { togglePlaybackSetting() }
activity_track_speed_click_area.setOnClickListener { showPlaybackSpeedPicker() }
private fun setupButtons() = binding.apply {
activityTrackToggleShuffle.setOnClickListener { withPlayer { toggleShuffle() } }
activityTrackPrevious.setOnClickListener { withPlayer { forceSeekToPrevious() } }
activityTrackPlayPause.setOnClickListener { togglePlayback() }
activityTrackNext.setOnClickListener { withPlayer { forceSeekToNext() } }
activityTrackProgressCurrent.setOnClickListener { seekBack() }
activityTrackProgressMax.setOnClickListener { seekForward() }
activityTrackPlaybackSetting.setOnClickListener { togglePlaybackSetting() }
activityTrackSpeedClickArea.setOnClickListener { showPlaybackSpeedPicker() }
setupShuffleButton()
setupPlaybackSettingButton()
setupSeekbar()
arrayOf(activity_track_previous, activity_track_play_pause, activity_track_next).forEach {
arrayOf(activityTrackPrevious, activityTrackPlayPause, activityTrackNext).forEach {
it.applyColorFilter(getProperTextColor())
}
}
@ -162,11 +173,11 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
private fun setupNextTrackInfo(item: MediaItem?) {
val track = item?.toTrack()
if (track == null) {
next_track_holder.beGone()
binding.nextTrackHolder.beGone()
return
}
next_track_holder.beVisible()
binding.nextTrackHolder.beVisible()
val artist = if (track.artist.trim().isNotEmpty() && track.artist != MediaStore.UNKNOWN_STRING) {
"${track.artist}"
} else {
@ -174,10 +185,10 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
}
@SuppressLint("SetTextI18n")
next_track_label.text = "${getString(R.string.next_track)} ${track.title}$artist"
binding.nextTrackLabel.text = "${getString(R.string.next_track)} ${track.title}$artist"
getTrackCoverArt(track) { coverArt ->
val cornerRadius = resources.getDimension(R.dimen.rounded_corner_radius_small).toInt()
val cornerRadius = resources.getDimension(com.simplemobiletools.commons.R.dimen.rounded_corner_radius_small).toInt()
val wantedSize = resources.getDimension(R.dimen.song_image_size).toInt()
// change cover image manually only once loaded successfully to avoid blinking at fails and placeholders
@ -187,12 +198,12 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
size = Size(wantedSize, wantedSize),
onLoadFailed = {
runOnUiThread {
next_track_image.setImageDrawable(nextTrackPlaceholder)
binding.nextTrackImage.setImageDrawable(nextTrackPlaceholder)
}
},
onResourceReady = {
runOnUiThread {
next_track_image.setImageDrawable(it)
binding.nextTrackImage.setImageDrawable(it)
}
}
)
@ -216,17 +227,17 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
placeholder.applyColorFilter(getProperTextColor())
runOnUiThread {
activity_track_image.setImageDrawable(placeholder)
binding.activityTrackImage.setImageDrawable(placeholder)
}
},
onResourceReady = {
val coverHeight = it.intrinsicHeight
if (coverHeight > 0 && activity_track_image.height != coverHeight) {
activity_track_image.layoutParams.height = coverHeight
if (coverHeight > 0 && binding.activityTrackImage.height != coverHeight) {
binding.activityTrackImage.layoutParams.height = coverHeight
}
runOnUiThread {
activity_track_image.setImageDrawable(it)
binding.activityTrackImage.setImageDrawable(it)
}
}
)
@ -236,18 +247,20 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
@SuppressLint("ClickableViewAccessibility")
private fun setupFlingListener() {
val flingListener = object : GestureDetector.SimpleOnGestureListener() {
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
if (velocityY > 0 && velocityY > velocityX && e2.y - e1.y > SWIPE_DOWN_THRESHOLD) {
finish()
activity_track_top_shadow.animate().alpha(0f).start()
overridePendingTransition(0, R.anim.slide_down)
override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
if (e1 != null) {
if (velocityY > 0 && velocityY > velocityX && e2.y - e1.y > SWIPE_DOWN_THRESHOLD) {
finish()
binding.activityTrackTopShadow.animate().alpha(0f).start()
overridePendingTransition(0, com.simplemobiletools.commons.R.anim.slide_down)
}
}
return super.onFling(e1, e2, velocityX, velocityY)
}
}
val gestureDetector = GestureDetectorCompat(this, flingListener)
activity_track_holder.setOnTouchListener { v, event ->
binding.activityTrackHolder.setOnTouchListener { _, event ->
gestureDetector.onTouchEvent(event)
true
}
@ -265,7 +278,7 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
}
private fun setupShuffleButton(isShuffleEnabled: Boolean = config.isShuffleEnabled) {
activity_track_toggle_shuffle.apply {
binding.activityTrackToggleShuffle.apply {
applyColorFilter(if (isShuffleEnabled) getProperPrimaryColor() else getProperTextColor())
alpha = if (isShuffleEnabled) 1f else MEDIUM_ALPHA
contentDescription = getString(if (isShuffleEnabled) R.string.disable_shuffle else R.string.enable_shuffle)
@ -273,12 +286,12 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
}
private fun seekBack() {
activity_track_progressbar.progress += -SEEK_INTERVAL_S
binding.activityTrackProgressbar.progress += -SEEK_INTERVAL_S
withPlayer { seekBack() }
}
private fun seekForward() {
activity_track_progressbar.progress += SEEK_INTERVAL_S
binding.activityTrackProgressbar.progress += SEEK_INTERVAL_S
withPlayer { seekForward() }
}
@ -292,8 +305,14 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
}
}
private fun maybeUpdatePlaybackSettingButton(playbackSetting: PlaybackSetting) {
if (config.playbackSetting != PlaybackSetting.STOP_AFTER_CURRENT_TRACK) {
setupPlaybackSettingButton(playbackSetting)
}
}
private fun setupPlaybackSettingButton(playbackSetting: PlaybackSetting = config.playbackSetting) {
activity_track_playback_setting.apply {
binding.activityTrackPlaybackSetting.apply {
contentDescription = getString(playbackSetting.contentDescriptionStringRes)
setImageResource(playbackSetting.iconRes)
@ -305,13 +324,13 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
}
private fun setupSeekbar() {
activity_track_speed_icon.applyColorFilter(getProperTextColor())
binding.activityTrackSpeedIcon.applyColorFilter(getProperTextColor())
updatePlaybackSpeed(config.playbackSpeed)
activity_track_progressbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
binding.activityTrackProgressbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
val formattedProgress = progress.getFormattedDuration()
activity_track_progress_current.text = formattedProgress
binding.activityTrackProgressCurrent.text = formattedProgress
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
@ -330,15 +349,15 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
override fun updatePlaybackSpeed(speed: Float) {
val isSlow = speed < 1f
if (isSlow != activity_track_speed.tag as? Boolean) {
activity_track_speed.tag = isSlow
if (isSlow != binding.activityTrackSpeed.tag as? Boolean) {
binding.activityTrackSpeed.tag = isSlow
val drawableId = if (isSlow) R.drawable.ic_playback_speed_slow_vector else R.drawable.ic_playback_speed_vector
activity_track_speed_icon.setImageDrawable(resources.getDrawable(drawableId))
binding.activityTrackSpeedIcon.setImageDrawable(resources.getDrawable(drawableId))
}
@SuppressLint("SetTextI18n")
activity_track_speed.text = "${DecimalFormat("#.##").format(speed)}x"
binding.activityTrackSpeed.text = "${DecimalFormat("#.##").format(speed)}x"
withPlayer {
setPlaybackSpeed(speed)
}
@ -354,7 +373,7 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
override fun onIsPlayingChanged(isPlaying: Boolean) = updatePlayerState()
override fun onRepeatModeChanged(repeatMode: Int) = setupPlaybackSettingButton(getPlaybackSetting(repeatMode))
override fun onRepeatModeChanged(repeatMode: Int) = maybeUpdatePlaybackSettingButton(getPlaybackSetting(repeatMode))
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) = setupShuffleButton(shuffleModeEnabled)
@ -363,7 +382,7 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
if (mediaItem == null) {
finish()
} else {
activity_track_progressbar.progress = 0
binding.activityTrackProgressbar.progress = 0
updateTrackInfo()
}
}
@ -387,7 +406,7 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
updateProgress(currentPosition)
updatePlayPause(isPlaying)
setupShuffleButton(shuffleModeEnabled)
setupPlaybackSettingButton(getPlaybackSetting(repeatMode))
maybeUpdatePlaybackSettingButton(getPlaybackSetting(repeatMode))
}
}
@ -407,10 +426,10 @@ class TrackActivity : SimpleControllerActivity(), PlaybackSpeedListener {
}
private fun updateProgress(currentPosition: Long) {
activity_track_progressbar.progress = currentPosition.milliseconds.inWholeSeconds.toInt()
binding.activityTrackProgressbar.progress = currentPosition.milliseconds.inWholeSeconds.toInt()
}
private fun updatePlayPause(isPlaying: Boolean) {
activity_track_play_pause.updatePlayPauseIcon(isPlaying, getProperTextColor())
binding.activityTrackPlayPause.updatePlayPauseIcon(isPlaying, getProperTextColor())
}
}

View file

@ -27,6 +27,7 @@ import com.simplemobiletools.musicplayer.adapters.TracksAdapter.Companion.TYPE_F
import com.simplemobiletools.musicplayer.adapters.TracksAdapter.Companion.TYPE_PLAYLIST
import com.simplemobiletools.musicplayer.adapters.TracksAdapter.Companion.TYPE_TRACKS
import com.simplemobiletools.musicplayer.adapters.TracksHeaderAdapter
import com.simplemobiletools.musicplayer.databinding.ActivityTracksBinding
import com.simplemobiletools.musicplayer.dialogs.ChangeSortingDialog
import com.simplemobiletools.musicplayer.dialogs.ExportPlaylistDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
@ -36,8 +37,6 @@ import com.simplemobiletools.musicplayer.extensions.getMediaStoreIdFromPath
import com.simplemobiletools.musicplayer.helpers.*
import com.simplemobiletools.musicplayer.helpers.M3uExporter.ExportResult
import com.simplemobiletools.musicplayer.models.*
import kotlinx.android.synthetic.main.activity_tracks.*
import kotlinx.android.synthetic.main.view_current_track_bar.current_track_bar
import org.greenrobot.eventbus.EventBus
import java.io.OutputStream
@ -54,31 +53,33 @@ class TracksActivity : SimpleMusicActivity() {
private var sourceType = 0
private var lastFilePickerPath = ""
private val binding by viewBinding(ActivityTracksBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tracks)
setContentView(binding.root)
setupOptionsMenu()
refreshMenuItems()
updateMaterialActivityViews(tracks_coordinator, tracks_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(tracks_list, tracks_toolbar)
updateMaterialActivityViews(binding.tracksCoordinator, binding.tracksHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.tracksList, binding.tracksToolbar)
val properPrimaryColor = getProperPrimaryColor()
tracks_fastscroller.updateColors(properPrimaryColor)
tracks_placeholder.setTextColor(getProperTextColor())
tracks_placeholder_2.setTextColor(properPrimaryColor)
tracks_placeholder_2.underlineText()
tracks_placeholder_2.setOnClickListener {
binding.tracksFastscroller.updateColors(properPrimaryColor)
binding.tracksPlaceholder.setTextColor(getProperTextColor())
binding.tracksPlaceholder2.setTextColor(properPrimaryColor)
binding.tracksPlaceholder2.underlineText()
binding.tracksPlaceholder2.setOnClickListener {
addFolderToPlaylist()
}
setupCurrentTrackBar(current_track_bar)
setupCurrentTrackBar(binding.currentTrackBar.root)
}
override fun onResume() {
super.onResume()
setupToolbar(tracks_toolbar, NavigationIcon.Arrow, searchMenuItem = searchMenuItem)
setupToolbar(binding.tracksToolbar, NavigationIcon.Arrow, searchMenuItem = searchMenuItem)
refreshTracks()
}
@ -95,7 +96,7 @@ class TracksActivity : SimpleMusicActivity() {
}
private fun refreshMenuItems() {
tracks_toolbar.menu.apply {
binding.tracksToolbar.menu.apply {
findItem(R.id.search).isVisible = sourceType != TYPE_ALBUM
findItem(R.id.sort).isVisible = sourceType != TYPE_ALBUM
findItem(R.id.add_file_to_playlist).isVisible = sourceType == TYPE_PLAYLIST
@ -105,8 +106,8 @@ class TracksActivity : SimpleMusicActivity() {
}
private fun setupOptionsMenu() {
setupSearch(tracks_toolbar.menu)
tracks_toolbar.setOnMenuItemClickListener { menuItem ->
setupSearch(binding.tracksToolbar.menu)
binding.tracksToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.sort -> showSortingDialog()
R.id.add_file_to_playlist -> addFileToPlaylist()
@ -173,11 +174,11 @@ class TracksActivity : SimpleMusicActivity() {
folder = intent.getStringExtra(FOLDER)
if (folder != null) {
sourceType = TYPE_FOLDER
tracks_placeholder_2.beGone()
binding.tracksPlaceholder2.beGone()
}
val titleToUse = playlist?.title ?: album?.title ?: genre?.title ?: folder ?: ""
tracks_toolbar.title = titleToUse
binding.tracksToolbar.title = titleToUse
refreshMenuItems()
ensureBackgroundThread {
@ -187,13 +188,14 @@ class TracksActivity : SimpleMusicActivity() {
TYPE_PLAYLIST -> {
val playlistTracks = audioHelper.getPlaylistTracks(playlist!!.id)
runOnUiThread {
tracks_placeholder.beVisibleIf(playlistTracks.isEmpty())
tracks_placeholder_2.beVisibleIf(playlistTracks.isEmpty())
binding.tracksPlaceholder.beVisibleIf(playlistTracks.isEmpty())
binding.tracksPlaceholder2.beVisibleIf(playlistTracks.isEmpty())
}
tracks.addAll(playlistTracks)
listItems.addAll(tracks)
}
TYPE_ALBUM -> {
val albumTracks = audioHelper.getAlbumTracks(album.id)
tracks.addAll(albumTracks)
@ -202,14 +204,16 @@ class TracksActivity : SimpleMusicActivity() {
listItems.add(header)
listItems.addAll(tracks)
}
TYPE_TRACKS -> {
val genreTracks = audioHelper.getGenreTracks(genre.id)
tracks.addAll(genreTracks)
}
else -> {
val folderTracks = audioHelper.getFolderTracks(folder.orEmpty())
runOnUiThread {
tracks_placeholder.beVisibleIf(folderTracks.isEmpty())
binding.tracksPlaceholder.beVisibleIf(folderTracks.isEmpty())
}
tracks.addAll(folderTracks)
@ -219,26 +223,26 @@ class TracksActivity : SimpleMusicActivity() {
runOnUiThread {
if (sourceType == TYPE_ALBUM) {
val currAdapter = tracks_list.adapter
val currAdapter = binding.tracksList.adapter
if (currAdapter == null) {
TracksHeaderAdapter(this, listItems, tracks_list) {
TracksHeaderAdapter(this, listItems, binding.tracksList) {
itemClicked(it as Track)
}.apply {
tracks_list.adapter = this
binding.tracksList.adapter = this
}
if (areSystemAnimationsEnabled) {
tracks_list.scheduleLayoutAnimation()
binding.tracksList.scheduleLayoutAnimation()
}
} else {
(currAdapter as TracksHeaderAdapter).updateItems(listItems)
}
} else {
val currAdapter = tracks_list.adapter
val currAdapter = binding.tracksList.adapter
if (currAdapter == null) {
TracksAdapter(
activity = this,
recyclerView = tracks_list,
recyclerView = binding.tracksList,
sourceType = sourceType,
folder = folder,
playlist = playlist,
@ -246,11 +250,11 @@ class TracksActivity : SimpleMusicActivity() {
) {
itemClicked(it as Track)
}.apply {
tracks_list.adapter = this
binding.tracksList.adapter = this
}
if (areSystemAnimationsEnabled) {
tracks_list.scheduleLayoutAnimation()
binding.tracksList.scheduleLayoutAnimation()
}
} else {
(currAdapter as TracksAdapter).updateItems(tracks)
@ -260,9 +264,11 @@ class TracksActivity : SimpleMusicActivity() {
}
}
private fun getTracksAdapter() = binding.tracksList.adapter as? TracksAdapter
private fun showSortingDialog() {
ChangeSortingDialog(this, ACTIVITY_PLAYLIST_FOLDER, playlist, folder) {
val adapter = tracks_list.adapter as? TracksAdapter ?: return@ChangeSortingDialog
val adapter = getTracksAdapter() ?: return@ChangeSortingDialog
val tracks = adapter.items
val sorting = when (sourceType) {
TYPE_PLAYLIST -> config.getProperPlaylistSorting(playlist?.id ?: -1)
@ -286,7 +292,7 @@ class TracksActivity : SimpleMusicActivity() {
if (path.isAudioFast()) {
addTrackFromPath(path, true)
} else {
toast(R.string.invalid_file_format)
toast(com.simplemobiletools.commons.R.string.invalid_file_format)
}
}
}
@ -300,7 +306,7 @@ class TracksActivity : SimpleMusicActivity() {
addTrackFromPath(path, false)
}
} else {
toast(R.string.unknown_error_occurred)
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
} else {
var track = audioHelper.getTrack(mediaStoreId)
@ -333,20 +339,20 @@ class TracksActivity : SimpleMusicActivity() {
}
private fun onSearchOpened() {
tracksIgnoringSearch = (tracks_list.adapter as? TracksAdapter)?.items ?: return
tracksIgnoringSearch = getTracksAdapter()?.items ?: return
}
private fun onSearchClosed() {
(tracks_list.adapter as? TracksAdapter)?.updateItems(tracksIgnoringSearch)
tracks_placeholder.beGoneIf(tracksIgnoringSearch.isNotEmpty())
getTracksAdapter()?.updateItems(tracksIgnoringSearch)
binding.tracksPlaceholder.beGoneIf(tracksIgnoringSearch.isNotEmpty())
}
private fun onSearchQueryChanged(text: String) {
val filtered = tracksIgnoringSearch.filter {
it.title.contains(text, true) || ("${it.artist} - ${it.album}").contains(text, true)
}.toMutableList() as ArrayList<Track>
(tracks_list.adapter as? TracksAdapter)?.updateItems(filtered, text)
tracks_placeholder.beGoneIf(filtered.isNotEmpty())
getTracksAdapter()?.updateItems(filtered, text)
binding.tracksPlaceholder.beGoneIf(filtered.isNotEmpty())
}
private fun refreshPlaylist() {
@ -354,16 +360,16 @@ class TracksActivity : SimpleMusicActivity() {
val newTracks = audioHelper.getPlaylistTracks(playlist!!.id)
runOnUiThread {
(tracks_list.adapter as? TracksAdapter)?.updateItems(newTracks)
tracks_placeholder.beVisibleIf(newTracks.isEmpty())
tracks_placeholder_2.beVisibleIf(newTracks.isEmpty())
getTracksAdapter()?.updateItems(newTracks)
binding.tracksPlaceholder.beVisibleIf(newTracks.isEmpty())
binding.tracksPlaceholder2.beVisibleIf(newTracks.isEmpty())
}
}
private fun itemClicked(track: Track) {
val tracks = when (sourceType) {
TYPE_ALBUM -> (tracks_list.adapter as? TracksHeaderAdapter)?.items?.filterIsInstance<Track>()
else -> (tracks_list.adapter as? TracksAdapter)?.items
TYPE_ALBUM -> (binding.tracksList.adapter as? TracksHeaderAdapter)?.items?.filterIsInstance<Track>()
else -> getTracksAdapter()?.items
} ?: ArrayList()
handleNotificationPermission { granted ->
@ -371,7 +377,7 @@ class TracksActivity : SimpleMusicActivity() {
val startIndex = tracks.indexOf(track)
prepareAndPlay(tracks, startIndex)
} else {
PermissionRequiredDialog(this, R.string.allow_notifications_music_player, { openNotificationSettings() })
PermissionRequiredDialog(this, com.simplemobiletools.commons.R.string.allow_notifications_music_player, { openNotificationSettings() })
}
}
}
@ -387,7 +393,7 @@ class TracksActivity : SimpleMusicActivity() {
try {
startActivityForResult(this, PICK_EXPORT_FILE_INTENT)
} catch (e: ActivityNotFoundException) {
toast(R.string.system_service_disabled, Toast.LENGTH_LONG)
toast(com.simplemobiletools.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
showErrorToast(e)
}
@ -407,19 +413,18 @@ class TracksActivity : SimpleMusicActivity() {
}
private fun exportPlaylistTo(outputStream: OutputStream?) {
val tracks = (tracks_list.adapter as TracksAdapter).items
if (tracks.isEmpty()) {
toast(R.string.no_entries_for_exporting)
val tracks = getTracksAdapter()?.items
if (tracks.isNullOrEmpty()) {
toast(com.simplemobiletools.commons.R.string.no_entries_for_exporting)
return
}
M3uExporter(this).exportPlaylist(outputStream, tracks) { result ->
toast(
when (result) {
ExportResult.EXPORT_OK -> R.string.exporting_successful
ExportResult.EXPORT_PARTIAL -> R.string.exporting_some_entries_failed
else -> R.string.exporting_failed
ExportResult.EXPORT_OK -> com.simplemobiletools.commons.R.string.exporting_successful
ExportResult.EXPORT_PARTIAL -> com.simplemobiletools.commons.R.string.exporting_some_entries_failed
else -> com.simplemobiletools.commons.R.string.exporting_failed
}
)
}

View file

@ -12,16 +12,10 @@ import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.WidgetConfigBinding
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.helpers.MyWidgetProvider
import com.simplemobiletools.musicplayer.playback.PlaybackService
import kotlinx.android.synthetic.main.widget.song_info_artist
import kotlinx.android.synthetic.main.widget.song_info_title
import kotlinx.android.synthetic.main.widget.view.widget_background
import kotlinx.android.synthetic.main.widget_config.*
import kotlinx.android.synthetic.main.widget_controls.next_btn
import kotlinx.android.synthetic.main.widget_controls.play_pause_btn
import kotlinx.android.synthetic.main.widget_controls.previous_btn
class WidgetConfigureActivity : SimpleActivity() {
private var mBgAlpha = 0f
@ -31,11 +25,13 @@ class WidgetConfigureActivity : SimpleActivity() {
private var mBgColorWithoutTransparency = 0
private var mFeatureLockedDialog: FeatureLockedDialog? = null
private val binding by viewBinding(WidgetConfigBinding::inflate)
public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false
super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED)
setContentView(R.layout.widget_config)
setContentView(binding.root)
initVariables()
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
@ -45,20 +41,21 @@ class WidgetConfigureActivity : SimpleActivity() {
finish()
}
config_save.setOnClickListener { saveConfig() }
config_bg_color.setOnClickListener { pickBackgroundColor() }
config_text_color.setOnClickListener { pickTextColor() }
binding.configSave.setOnClickListener { saveConfig() }
binding.configBgColor.setOnClickListener { pickBackgroundColor() }
binding.configTextColor.setOnClickListener { pickTextColor() }
val primaryColor = getProperPrimaryColor()
config_bg_seekbar.setColors(mTextColor, primaryColor, primaryColor)
val currSong = PlaybackService.currentMediaItem?.mediaMetadata
if (currSong != null) {
song_info_title.text = currSong.title
song_info_artist.text = currSong.artist
} else {
song_info_title.text = getString(R.string.artist)
song_info_artist.text = getString(R.string.song_title)
binding.configBgSeekbar.setColors(mTextColor, primaryColor, primaryColor)
binding.configPlayer.apply {
val currSong = PlaybackService.currentMediaItem?.mediaMetadata
if (currSong != null) {
songInfoTitle.text = currSong.title
songInfoArtist.text = currSong.artist
} else {
songInfoTitle.text = getString(com.simplemobiletools.commons.R.string.artist)
songInfoArtist.text = getString(com.simplemobiletools.commons.R.string.song_title)
}
}
if (!isCustomizingColors && !isOrWasThankYouInstalled()) {
@ -82,16 +79,16 @@ class WidgetConfigureActivity : SimpleActivity() {
mBgAlpha = Color.alpha(mBgColor) / 255.toFloat()
mBgColorWithoutTransparency = Color.rgb(Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor))
config_bg_seekbar.progress = (mBgAlpha * 100).toInt()
binding.configBgSeekbar.progress = (mBgAlpha * 100).toInt()
updateBackgroundColor()
config_bg_seekbar.onSeekBarChangeListener { progress ->
binding.configBgSeekbar.onSeekBarChangeListener { progress ->
mBgAlpha = progress / 100.toFloat()
updateBackgroundColor()
}
mTextColor = config.widgetTextColor
if (mTextColor == resources.getColor(R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(R.color.you_primary_color, theme)
if (mTextColor == resources.getColor(com.simplemobiletools.commons.R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(com.simplemobiletools.commons.R.color.you_primary_color, theme)
}
updateTextColor()
@ -133,23 +130,23 @@ class WidgetConfigureActivity : SimpleActivity() {
}
}
private fun updateBackgroundColor() {
private fun updateBackgroundColor() = binding.apply {
mBgColor = mBgColorWithoutTransparency.adjustAlpha(mBgAlpha)
config_player.widget_background.applyColorFilter(mBgColor)
config_bg_color.setFillWithStroke(mBgColor, mBgColor)
config_save.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
configPlayer.widgetBackground.applyColorFilter(mBgColor)
configBgColor.setFillWithStroke(mBgColor, mBgColor)
configSave.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
}
private fun updateTextColor() {
config_text_color.setFillWithStroke(mTextColor, mTextColor)
private fun updateTextColor() = binding.apply {
configTextColor.setFillWithStroke(mTextColor, mTextColor)
song_info_title.setTextColor(mTextColor)
song_info_artist.setTextColor(mTextColor)
config_save.setTextColor(getProperPrimaryColor().getContrastColor())
configPlayer.songInfoTitle.setTextColor(mTextColor)
configPlayer.songInfoArtist.setTextColor(mTextColor)
configSave.setTextColor(getProperPrimaryColor().getContrastColor())
previous_btn.drawable.applyColorFilter(mTextColor)
play_pause_btn.drawable.applyColorFilter(mTextColor)
next_btn.drawable.applyColorFilter(mTextColor)
configPlayer.widgetControls.previousBtn.drawable.applyColorFilter(mTextColor)
configPlayer.widgetControls.playPauseBtn.drawable.applyColorFilter(mTextColor)
configPlayer.widgetControls.nextBtn.drawable.applyColorFilter(mTextColor)
}
private fun pickBackgroundColor() {

View file

@ -10,20 +10,23 @@ import com.simplemobiletools.commons.extensions.setupViewBackground
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.databinding.ItemAlbumBinding
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.getAlbumCoverArt
import com.simplemobiletools.musicplayer.inlines.indexOfFirstOrNull
import com.simplemobiletools.musicplayer.models.Album
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.item_album.view.album_frame
import kotlinx.android.synthetic.main.item_album.view.album_title
import kotlinx.android.synthetic.main.item_album.view.album_tracks
class AlbumsAdapter(activity: BaseSimpleActivity, items: ArrayList<Album>, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) :
BaseMusicAdapter<Album>(items, activity, recyclerView, itemClick), RecyclerViewFastScroller.OnPopupTextUpdate {
override fun getActionMenuId() = R.menu.cab_albums
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_album, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemAlbumBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val album = items.getOrNull(position) ?: return
@ -48,19 +51,19 @@ class AlbumsAdapter(activity: BaseSimpleActivity, items: ArrayList<Album>, recyc
}
override fun getSelectedTracks(): List<Track> {
return ctx.audioHelper.getAlbumTracks(getSelectedItems())
return context.audioHelper.getAlbumTracks(getSelectedItems())
}
private fun askConfirmDelete() {
ConfirmationDialog(ctx) {
ConfirmationDialog(context) {
ensureBackgroundThread {
val selectedAlbums = getSelectedItems()
val positions = selectedAlbums.mapNotNull { album -> items.indexOfFirstOrNull { it.id == album.id } } as ArrayList<Int>
val tracks = ctx.audioHelper.getAlbumTracks(selectedAlbums)
ctx.audioHelper.deleteAlbums(selectedAlbums)
val tracks = context.audioHelper.getAlbumTracks(selectedAlbums)
context.audioHelper.deleteAlbums(selectedAlbums)
ctx.deleteTracks(tracks) {
ctx.runOnUiThread {
context.deleteTracks(tracks) {
context.runOnUiThread {
positions.sortDescending()
removeSelectedItems(positions)
positions.forEach {
@ -75,21 +78,21 @@ class AlbumsAdapter(activity: BaseSimpleActivity, items: ArrayList<Album>, recyc
}
private fun setupView(view: View, album: Album) {
view.apply {
setupViewBackground(ctx)
album_frame?.isSelected = selectedKeys.contains(album.hashCode())
album_title.text = if (textToHighlight.isEmpty()) album.title else album.title.highlightTextPart(textToHighlight, properPrimaryColor)
album_title.setTextColor(textColor)
ItemAlbumBinding.bind(view).apply {
root.setupViewBackground(context)
albumFrame.isSelected = selectedKeys.contains(album.hashCode())
albumTitle.text = if (textToHighlight.isEmpty()) album.title else album.title.highlightTextPart(textToHighlight, properPrimaryColor)
albumTitle.setTextColor(textColor)
val tracks = resources.getQuantityString(R.plurals.tracks_plural, album.trackCnt, album.trackCnt)
album_tracks.text = tracks
album_tracks.setTextColor(textColor)
albumTracks.text = tracks
albumTracks.setTextColor(textColor)
ctx.getAlbumCoverArt(album) { coverArt ->
loadImage(findViewById(R.id.album_image), coverArt, placeholderBig)
context.getAlbumCoverArt(album) { coverArt ->
loadImage(albumImage, coverArt, placeholderBig)
}
}
}
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(ctx.config.albumSorting) ?: ""
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(context.config.albumSorting) ?: ""
}

View file

@ -13,6 +13,9 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.databinding.ItemAlbumBinding
import com.simplemobiletools.musicplayer.databinding.ItemSectionBinding
import com.simplemobiletools.musicplayer.databinding.ItemTrackBinding
import com.simplemobiletools.musicplayer.dialogs.EditDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.getAlbumCoverArt
@ -22,11 +25,6 @@ import com.simplemobiletools.musicplayer.models.Album
import com.simplemobiletools.musicplayer.models.AlbumSection
import com.simplemobiletools.musicplayer.models.ListItem
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.item_album.view.album_frame
import kotlinx.android.synthetic.main.item_album.view.album_title
import kotlinx.android.synthetic.main.item_album.view.album_tracks
import kotlinx.android.synthetic.main.item_section.view.item_section
import kotlinx.android.synthetic.main.item_track.view.*
// we show both albums and individual tracks here
class AlbumsTracksAdapter(
@ -41,13 +39,13 @@ class AlbumsTracksAdapter(
override fun getActionMenuId() = R.menu.cab_albums_tracks
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = when (viewType) {
ITEM_SECTION -> R.layout.item_section
ITEM_ALBUM -> R.layout.item_album
else -> R.layout.item_track
val binding = when (viewType) {
ITEM_SECTION -> ItemSectionBinding.inflate(layoutInflater, parent, false)
ITEM_ALBUM -> ItemAlbumBinding.inflate(layoutInflater, parent, false)
else -> ItemTrackBinding.inflate(layoutInflater, parent, false)
}
return createViewHolder(layout, parent)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@ -99,7 +97,7 @@ class AlbumsTracksAdapter(
override fun getIsItemSelectable(position: Int) = items[position] !is AlbumSection
private fun askConfirmDelete() {
ConfirmationDialog(ctx) {
ConfirmationDialog(context) {
ensureBackgroundThread {
val positions = ArrayList<Int>()
val selectedTracks = getAllSelectedTracks()
@ -108,8 +106,8 @@ class AlbumsTracksAdapter(
positions += selectedTracks.mapNotNull { track -> items.indexOfFirstOrNull { it is Track && it.mediaStoreId == track.mediaStoreId } }
positions += selectedAlbums.mapNotNull { album -> items.indexOfFirstOrNull { it is Album && it.id == album.id } }
ctx.deleteTracks(selectedTracks) {
ctx.runOnUiThread {
context.deleteTracks(selectedTracks) {
context.runOnUiThread {
positions.sortDescending()
removeSelectedItems(positions)
positions.forEach {
@ -118,7 +116,7 @@ class AlbumsTracksAdapter(
// finish activity if all tracks are deleted
if (items.none { it is Track }) {
ctx.finish()
context.finish()
}
}
}
@ -128,50 +126,51 @@ class AlbumsTracksAdapter(
override fun getAllSelectedTracks(): List<Track> {
val tracks = getSelectedTracks().toMutableList()
tracks.addAll(ctx.audioHelper.getAlbumTracks(getSelectedAlbums()))
tracks.addAll(context.audioHelper.getAlbumTracks(getSelectedAlbums()))
return tracks
}
private fun getSelectedAlbums(): List<Album> = getSelectedItems().filterIsInstance<Album>().toList()
private fun setupAlbum(view: View, album: Album) {
view.apply {
album_frame?.isSelected = selectedKeys.contains(album.hashCode())
album_title.text = album.title
album_title.setTextColor(textColor)
album_tracks.text = resources.getQuantityString(R.plurals.tracks_plural, album.trackCnt, album.trackCnt)
album_tracks.setTextColor(textColor)
ItemAlbumBinding.bind(view).apply {
root.setupViewBackground(context)
albumFrame.isSelected = selectedKeys.contains(album.hashCode())
albumTitle.text = album.title
albumTitle.setTextColor(textColor)
albumTracks.text = resources.getQuantityString(R.plurals.tracks_plural, album.trackCnt, album.trackCnt)
albumTracks.setTextColor(textColor)
ctx.getAlbumCoverArt(album) { coverArt ->
loadImage(findViewById(R.id.album_image), coverArt, placeholderBig)
context.getAlbumCoverArt(album) { coverArt ->
loadImage(albumImage, coverArt, placeholderBig)
}
}
}
private fun setupTrack(view: View, track: Track) {
view.apply {
setupViewBackground(ctx)
track_frame?.isSelected = selectedKeys.contains(track.hashCode())
track_title.text = track.title
track_title.setTextColor(textColor)
track_info.text = track.album
track_info.setTextColor(textColor)
ItemTrackBinding.bind(view).apply {
root.setupViewBackground(context)
trackFrame.isSelected = selectedKeys.contains(track.hashCode())
trackTitle.text = track.title
trackTitle.setTextColor(textColor)
trackInfo.text = track.album
trackInfo.setTextColor(textColor)
track_id.beGone()
track_image.beVisible()
track_duration.text = track.duration.getFormattedDuration()
track_duration.setTextColor(textColor)
trackId.beGone()
trackImage.beVisible()
trackDuration.text = track.duration.getFormattedDuration()
trackDuration.setTextColor(textColor)
ctx.getTrackCoverArt(track) { coverArt ->
loadImage(findViewById(R.id.track_image), coverArt, placeholder)
context.getTrackCoverArt(track) { coverArt ->
loadImage(trackImage, coverArt, placeholder)
}
}
}
private fun setupSection(view: View, section: AlbumSection) {
view.apply {
item_section.text = section.title
item_section.setTextColor(textColor)
ItemSectionBinding.bind(view).apply {
itemSection.text = section.title
itemSection.setTextColor(textColor)
}
}
@ -186,7 +185,7 @@ class AlbumsTracksAdapter(
private fun displayEditDialog() {
getSelectedTracks().firstOrNull()?.let { selectedTrack ->
EditDialog(ctx as SimpleActivity, selectedTrack) { track ->
EditDialog(context as SimpleActivity, selectedTrack) { track ->
val trackIndex = items.indexOfFirst { (it as? Track)?.mediaStoreId == track.mediaStoreId }
if (trackIndex != -1) {
items[trackIndex] = track
@ -194,7 +193,7 @@ class AlbumsTracksAdapter(
finishActMode()
}
ctx.refreshQueueAndTracks(track)
context.refreshQueueAndTracks(track)
}
}
}

View file

@ -11,20 +11,21 @@ import com.simplemobiletools.commons.extensions.setupViewBackground
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ItemArtistBinding
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.inlines.indexOfFirstOrNull
import com.simplemobiletools.musicplayer.models.Artist
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.item_artist.view.artist_albums_tracks
import kotlinx.android.synthetic.main.item_artist.view.artist_frame
import kotlinx.android.synthetic.main.item_artist.view.artist_title
class ArtistsAdapter(activity: BaseSimpleActivity, items: ArrayList<Artist>, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) :
BaseMusicAdapter<Artist>(items, activity, recyclerView, itemClick), RecyclerViewFastScroller.OnPopupTextUpdate {
override fun getActionMenuId() = R.menu.cab_artists
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_artist, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemArtistBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val artist = items.getOrNull(position) ?: return
@ -49,20 +50,20 @@ class ArtistsAdapter(activity: BaseSimpleActivity, items: ArrayList<Artist>, rec
}
override fun getSelectedTracks(): ArrayList<Track> {
val albums = ctx.audioHelper.getArtistAlbums(getSelectedItems())
return ctx.audioHelper.getAlbumTracks(albums)
val albums = context.audioHelper.getArtistAlbums(getSelectedItems())
return context.audioHelper.getAlbumTracks(albums)
}
private fun askConfirmDelete() {
ConfirmationDialog(ctx) {
ConfirmationDialog(context) {
ensureBackgroundThread {
val selectedArtists = getSelectedItems()
val positions = selectedArtists.mapNotNull { artist -> items.indexOfFirstOrNull { it.id == artist.id } } as ArrayList<Int>
val tracks = ctx.audioHelper.getArtistTracks(selectedArtists)
val tracks = context.audioHelper.getArtistTracks(selectedArtists)
ctx.audioHelper.deleteArtists(selectedArtists)
ctx.deleteTracks(tracks) {
ctx.runOnUiThread {
context.audioHelper.deleteArtists(selectedArtists)
context.deleteTracks(tracks) {
context.runOnUiThread {
positions.sortDescending()
removeSelectedItems(positions)
positions.forEach {
@ -77,23 +78,23 @@ class ArtistsAdapter(activity: BaseSimpleActivity, items: ArrayList<Artist>, rec
}
private fun setupView(view: View, artist: Artist) {
view.apply {
setupViewBackground(ctx)
artist_frame?.isSelected = selectedKeys.contains(artist.hashCode())
artist_title.text = if (textToHighlight.isEmpty()) artist.title else artist.title.highlightTextPart(textToHighlight, properPrimaryColor)
artist_title.setTextColor(textColor)
ItemArtistBinding.bind(view).apply {
root.setupViewBackground(context)
artistFrame.isSelected = selectedKeys.contains(artist.hashCode())
artistTitle.text = if (textToHighlight.isEmpty()) artist.title else artist.title.highlightTextPart(textToHighlight, properPrimaryColor)
artistTitle.setTextColor(textColor)
val albums = resources.getQuantityString(R.plurals.albums_plural, artist.albumCnt, artist.albumCnt)
val tracks = resources.getQuantityString(R.plurals.tracks_plural, artist.trackCnt, artist.trackCnt)
@SuppressLint("SetTextI18n")
artist_albums_tracks.text = "$albums, $tracks"
artist_albums_tracks.setTextColor(textColor)
artistAlbumsTracks.text = "$albums, $tracks"
artistAlbumsTracks.setTextColor(textColor)
ctx.getArtistCoverArt(artist) { coverArt ->
loadImage(findViewById(R.id.artist_image), coverArt, placeholder)
context.getArtistCoverArt(artist) { coverArt ->
loadImage(artistImage, coverArt, placeholder)
}
}
}
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(ctx.config.artistSorting) ?: ""
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(context.config.artistSorting) ?: ""
}

View file

@ -1,5 +1,6 @@
package com.simplemobiletools.musicplayer.adapters
import android.annotation.SuppressLint
import android.graphics.drawable.Drawable
import android.view.Menu
import android.widget.ImageView
@ -9,9 +10,9 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleControllerActivity
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.helpers.TagHelper
@ -25,13 +26,17 @@ abstract class BaseMusicAdapter<Type>(
itemClick: (Any) -> Unit
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
val ctx = activity as SimpleControllerActivity
val context = activity as SimpleControllerActivity
var textToHighlight = ""
val tagHelper by lazy { TagHelper(ctx) }
val placeholder by lazy { resources.getSmallPlaceholder(textColor) }
val placeholderBig by lazy { resources.getBiggerPlaceholder(textColor) }
open val cornerRadius by lazy { resources.getDimension(R.dimen.rounded_corner_radius_small).toInt() }
val tagHelper by lazy { TagHelper(context) }
var placeholder = resources.getSmallPlaceholder(textColor)
var placeholderBig = resources.getBiggerPlaceholder(textColor)
open val cornerRadius by lazy { resources.getDimension(com.simplemobiletools.commons.R.dimen.rounded_corner_radius_small).toInt() }
init {
setupDragListener(true)
}
override fun getItemCount() = items.size
@ -91,8 +96,8 @@ abstract class BaseMusicAdapter<Type>(
fun addToQueue() {
ensureBackgroundThread {
val allSelectedTracks = getAllSelectedTracks()
ctx.runOnUiThread {
ctx.addTracksToQueue(allSelectedTracks) {
context.runOnUiThread {
context.addTracksToQueue(allSelectedTracks) {
finishActMode()
}
}
@ -102,8 +107,8 @@ abstract class BaseMusicAdapter<Type>(
fun playNextInQueue() {
ensureBackgroundThread {
getSelectedTracks().firstOrNull()?.let { selectedTrack ->
ctx.runOnUiThread {
ctx.playNextInQueue(selectedTrack) {
context.runOnUiThread {
context.playNextInQueue(selectedTrack) {
finishActMode()
}
}
@ -114,8 +119,8 @@ abstract class BaseMusicAdapter<Type>(
fun addToPlaylist() {
ensureBackgroundThread {
val allSelectedTracks = getAllSelectedTracks()
ctx.runOnUiThread {
ctx.addTracksToPlaylist(allSelectedTracks) {
context.runOnUiThread {
context.addTracksToPlaylist(allSelectedTracks) {
finishActMode()
notifyDataChanged()
}
@ -125,7 +130,7 @@ abstract class BaseMusicAdapter<Type>(
fun shareFiles() {
ensureBackgroundThread {
ctx.shareFiles(getAllSelectedTracks())
context.shareFiles(getAllSelectedTracks())
}
}
@ -136,8 +141,8 @@ abstract class BaseMusicAdapter<Type>(
return@ensureBackgroundThread
}
ctx.runOnUiThread {
ctx.showTrackProperties(selectedTracks)
context.runOnUiThread {
context.showTrackProperties(selectedTracks)
}
}
}
@ -147,13 +152,28 @@ abstract class BaseMusicAdapter<Type>(
.error(placeholder)
.transform(CenterCrop(), RoundedCorners(cornerRadius))
ctx.ensureActivityNotDestroyed {
Glide.with(ctx)
context.ensureActivityNotDestroyed {
Glide.with(context)
.load(resource)
.apply(options)
.into(imageView)
}
}
fun notifyDataChanged() = notifyItemRangeChanged(0, itemCount)
fun updateColors(newTextColor: Int) {
if (textColor != newTextColor || properPrimaryColor != context.getProperPrimaryColor()) {
updateTextColor(newTextColor)
updatePrimaryColor()
placeholder = resources.getSmallPlaceholder(textColor)
placeholderBig = resources.getBiggerPlaceholder(textColor)
notifyDataChanged()
}
}
@SuppressLint("NotifyDataSetChanged")
fun notifyDataChanged() = if (itemCount == 0) {
notifyDataSetChanged()
} else {
notifyItemRangeChanged(0, itemCount)
}
}

View file

@ -1,5 +1,6 @@
package com.simplemobiletools.musicplayer.adapters
import android.annotation.SuppressLint
import android.view.*
import android.widget.PopupMenu
import com.simplemobiletools.commons.activities.BaseSimpleActivity
@ -10,9 +11,8 @@ import com.simplemobiletools.commons.extensions.humanizePath
import com.simplemobiletools.commons.extensions.setupViewBackground
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ItemExcludedFolderBinding
import com.simplemobiletools.musicplayer.extensions.config
import kotlinx.android.synthetic.main.item_excluded_folder.view.*
class ExcludedFoldersAdapter(
activity: BaseSimpleActivity,
@ -24,13 +24,17 @@ class ExcludedFoldersAdapter(
private val config = activity.config
override fun getActionMenuId() = R.menu.cab_remove_only
init {
setupDragListener(true)
}
override fun getActionMenuId() = com.simplemobiletools.commons.R.menu.cab_remove_only
override fun prepareActionMode(menu: Menu) {}
override fun actionItemPressed(id: Int) {
when (id) {
R.id.cab_remove -> removeSelection()
com.simplemobiletools.commons.R.id.cab_remove -> removeSelection()
}
}
@ -46,11 +50,14 @@ class ExcludedFoldersAdapter(
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_excluded_folder, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemExcludedFolderBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val folder = folders[position]
holder.bindView(folder, true, true) { itemView, adapterPosition ->
holder.bindView(folder, allowSingleClick = true, allowLongClick = true) { itemView, _ ->
setupView(itemView, folder)
}
bindViewHolder(holder)
@ -61,21 +68,22 @@ class ExcludedFoldersAdapter(
private fun getSelectedItems() = folders.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<String>
private fun setupView(view: View, folder: String) {
view.apply {
setupViewBackground(activity)
excluded_folder_holder?.isSelected = selectedKeys.contains(folder.hashCode())
excluded_folder_title.apply {
ItemExcludedFolderBinding.bind(view).apply {
root.setupViewBackground(activity)
excludedFolderHolder.isSelected = selectedKeys.contains(folder.hashCode())
excludedFolderTitle.apply {
@SuppressLint("SetTextI18n")
text = context.humanizePath(folder) + "/"
setTextColor(context.getProperTextColor())
}
overflow_menu_icon.drawable.apply {
overflowMenuIcon.drawable.apply {
mutate()
setTint(activity.getProperTextColor())
}
overflow_menu_icon.setOnClickListener {
showPopupMenu(overflow_menu_anchor, folder)
overflowMenuIcon.setOnClickListener {
showPopupMenu(overflowMenuAnchor, folder)
}
}
}
@ -90,7 +98,7 @@ class ExcludedFoldersAdapter(
setOnMenuItemClickListener { item ->
val eventTypeId = folder.hashCode()
when (item.itemId) {
R.id.cab_remove -> {
com.simplemobiletools.commons.R.id.cab_remove -> {
executeItemMenuOperation(eventTypeId) {
removeSelection()
}

View file

@ -8,14 +8,12 @@ import com.simplemobiletools.commons.extensions.highlightTextPart
import com.simplemobiletools.commons.extensions.setupViewBackground
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ItemFolderBinding
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.models.Events
import com.simplemobiletools.musicplayer.models.Folder
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.item_folder.view.folder_frame
import kotlinx.android.synthetic.main.item_folder.view.folder_title
import kotlinx.android.synthetic.main.item_folder.view.folder_tracks
import org.greenrobot.eventbus.EventBus
class FoldersAdapter(
@ -24,7 +22,10 @@ class FoldersAdapter(
override fun getActionMenuId() = R.menu.cab_folders
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_folder, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemFolderBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val folder = items.getOrNull(position) ?: return
@ -43,7 +44,7 @@ class FoldersAdapter(
private fun excludeFolders() {
getSelectedItems().forEach {
ctx.config.addExcludedFolder(it.path)
context.config.addExcludedFolder(it.path)
}
finishActMode()
@ -53,24 +54,24 @@ class FoldersAdapter(
override fun getSelectedTracks(): List<Track> {
val tracks = arrayListOf<Track>()
getSelectedItems().forEach {
tracks += ctx.audioHelper.getFolderTracks(it.title)
tracks += context.audioHelper.getFolderTracks(it.title)
}
return tracks
}
private fun setupView(view: View, folder: Folder) {
view.apply {
setupViewBackground(ctx)
folder_frame?.isSelected = selectedKeys.contains(folder.hashCode())
folder_title.text = if (textToHighlight.isEmpty()) folder.title else folder.title.highlightTextPart(textToHighlight, properPrimaryColor)
folder_title.setTextColor(textColor)
ItemFolderBinding.bind(view).apply {
root.setupViewBackground(context)
folderFrame.isSelected = selectedKeys.contains(folder.hashCode())
folderTitle.text = if (textToHighlight.isEmpty()) folder.title else folder.title.highlightTextPart(textToHighlight, properPrimaryColor)
folderTitle.setTextColor(textColor)
val tracks = resources.getQuantityString(R.plurals.tracks_plural, folder.trackCount, folder.trackCount)
folder_tracks.text = tracks
folder_tracks.setTextColor(textColor)
folderTracks.text = tracks
folderTracks.setTextColor(textColor)
}
}
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(ctx.config.folderSorting) ?: ""
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(context.config.folderSorting) ?: ""
}

View file

@ -10,20 +10,23 @@ import com.simplemobiletools.commons.extensions.setupViewBackground
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.databinding.ItemGenreBinding
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.getGenreCoverArt
import com.simplemobiletools.musicplayer.inlines.indexOfFirstOrNull
import com.simplemobiletools.musicplayer.models.Genre
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.item_genre.view.genre_frame
import kotlinx.android.synthetic.main.item_genre.view.genre_title
import kotlinx.android.synthetic.main.item_genre.view.genre_tracks
class GenresAdapter(activity: BaseSimpleActivity, items: ArrayList<Genre>, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) :
BaseMusicAdapter<Genre>(items, activity, recyclerView, itemClick), RecyclerViewFastScroller.OnPopupTextUpdate {
override fun getActionMenuId() = R.menu.cab_genres
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_genre, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemGenreBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val genre = items.getOrNull(position) ?: return
@ -48,19 +51,19 @@ class GenresAdapter(activity: BaseSimpleActivity, items: ArrayList<Genre>, recyc
}
override fun getSelectedTracks(): ArrayList<Track> {
return ctx.audioHelper.getGenreTracks(getSelectedItems())
return context.audioHelper.getGenreTracks(getSelectedItems())
}
private fun askConfirmDelete() {
ConfirmationDialog(ctx) {
ConfirmationDialog(context) {
ensureBackgroundThread {
val selectedGenres = getSelectedItems()
val positions = selectedGenres.mapNotNull { genre -> items.indexOfFirstOrNull { it.id == genre.id } } as ArrayList<Int>
val tracks = ctx.audioHelper.getGenreTracks(selectedGenres)
ctx.audioHelper.deleteGenres(selectedGenres)
val tracks = context.audioHelper.getGenreTracks(selectedGenres)
context.audioHelper.deleteGenres(selectedGenres)
ctx.deleteTracks(tracks) {
ctx.runOnUiThread {
context.deleteTracks(tracks) {
context.runOnUiThread {
positions.sortDescending()
removeSelectedItems(positions)
positions.forEach {
@ -75,26 +78,26 @@ class GenresAdapter(activity: BaseSimpleActivity, items: ArrayList<Genre>, recyc
}
private fun setupView(view: View, genre: Genre) {
view.apply {
setupViewBackground(context)
genre_frame?.isSelected = selectedKeys.contains(genre.hashCode())
genre_title.text = if (textToHighlight.isEmpty()) {
ItemGenreBinding.bind(view).apply {
root.setupViewBackground(activity)
genreFrame.isSelected = selectedKeys.contains(genre.hashCode())
genreTitle.text = if (textToHighlight.isEmpty()) {
genre.title
} else {
genre.title.highlightTextPart(textToHighlight, properPrimaryColor)
}
genre_title.setTextColor(textColor)
genreTitle.setTextColor(textColor)
val tracks = resources.getQuantityString(R.plurals.tracks_plural, genre.trackCnt, genre.trackCnt)
genre_tracks.text = tracks
genre_tracks.setTextColor(textColor)
genreTracks.text = tracks
genreTracks.setTextColor(textColor)
context.getGenreCoverArt(genre) { coverArt ->
loadImage(findViewById(R.id.genre_image), coverArt, placeholderBig)
activity.getGenreCoverArt(genre) { coverArt ->
loadImage(genreImage, coverArt, placeholderBig)
}
}
}
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(ctx.config.genreSorting) ?: ""
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(context.config.genreSorting) ?: ""
}

View file

@ -13,15 +13,13 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.FileDirItem
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ItemPlaylistBinding
import com.simplemobiletools.musicplayer.dialogs.NewPlaylistDialog
import com.simplemobiletools.musicplayer.dialogs.RemovePlaylistDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.models.Events
import com.simplemobiletools.musicplayer.models.Playlist
import kotlinx.android.synthetic.main.item_playlist.view.playlist_frame
import kotlinx.android.synthetic.main.item_playlist.view.playlist_title
import kotlinx.android.synthetic.main.item_playlist.view.playlist_tracks
import org.greenrobot.eventbus.EventBus
class PlaylistsAdapter(
@ -30,7 +28,10 @@ class PlaylistsAdapter(
override fun getActionMenuId() = R.menu.cab_playlists
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_playlist, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemPlaylistBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val playlist = items.getOrNull(position) ?: return
@ -55,7 +56,7 @@ class PlaylistsAdapter(
}
private fun askConfirmDelete() {
RemovePlaylistDialog(ctx) { delete ->
RemovePlaylistDialog(context) { delete ->
val ids = getSelectedItems().map { it.id } as ArrayList<Int>
if (delete) {
ensureBackgroundThread {
@ -72,9 +73,9 @@ class PlaylistsAdapter(
private fun deletePlaylistSongs(ids: ArrayList<Int>, callback: () -> Unit) {
var cnt = ids.size
ids.map { id ->
val paths = ctx.audioHelper.getPlaylistTracks(id).map { it.path }
val paths = context.audioHelper.getPlaylistTracks(id).map { it.path }
val fileDirItems = paths.map { FileDirItem(it, it.getFilenameFromPath()) } as ArrayList<FileDirItem>
ctx.deleteFiles(fileDirItems) {
context.deleteFiles(fileDirItems) {
if (--cnt <= 0) {
callback()
}
@ -97,8 +98,8 @@ class PlaylistsAdapter(
items.removeAll(playlistsToDelete.toSet())
ensureBackgroundThread {
ctx.audioHelper.deletePlaylists(playlistsToDelete)
ctx.runOnUiThread {
context.audioHelper.deletePlaylists(playlistsToDelete)
context.runOnUiThread {
removeSelectedItems(positions)
}
@ -109,25 +110,25 @@ class PlaylistsAdapter(
private fun getItemWithKey(key: Int): Playlist? = items.firstOrNull { it.id == key }
private fun showRenameDialog() {
NewPlaylistDialog(ctx, items[getItemKeyPosition(selectedKeys.first())]) {
ctx.runOnUiThread {
NewPlaylistDialog(context, items[getItemKeyPosition(selectedKeys.first())]) {
context.runOnUiThread {
finishActMode()
}
}
}
private fun setupView(view: View, playlist: Playlist) {
view.apply {
setupViewBackground(ctx)
playlist_frame?.isSelected = selectedKeys.contains(playlist.id)
playlist_title.text = if (textToHighlight.isEmpty()) playlist.title else playlist.title.highlightTextPart(textToHighlight, properPrimaryColor)
playlist_title.setTextColor(textColor)
ItemPlaylistBinding.bind(view).apply {
root.setupViewBackground(context)
playlistFrame.isSelected = selectedKeys.contains(playlist.hashCode())
playlistTitle.text = if (textToHighlight.isEmpty()) playlist.title else playlist.title.highlightTextPart(textToHighlight, properPrimaryColor)
playlistTitle.setTextColor(textColor)
val tracks = resources.getQuantityString(R.plurals.tracks_plural, playlist.trackCount, playlist.trackCount)
playlist_tracks.text = tracks
playlist_tracks.setTextColor(textColor)
playlistTracks.text = tracks
playlistTracks.setTextColor(textColor)
}
}
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(ctx.config.playlistSorting) ?: ""
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(context.config.playlistSorting) ?: ""
}

View file

@ -17,14 +17,11 @@ import com.simplemobiletools.commons.interfaces.StartReorderDragListener
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.databinding.ItemTrackQueueBinding
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.helpers.EXTRA_SHUFFLE_INDICES
import com.simplemobiletools.musicplayer.models.Track
import com.simplemobiletools.musicplayer.playback.CustomCommands
import kotlinx.android.synthetic.main.item_track_queue.view.track_queue_drag_handle
import kotlinx.android.synthetic.main.item_track_queue.view.track_queue_duration
import kotlinx.android.synthetic.main.item_track_queue.view.track_queue_frame
import kotlinx.android.synthetic.main.item_track_queue.view.track_queue_title
class QueueAdapter(activity: SimpleActivity, items: ArrayList<Track>, var currentTrack: Track? = null, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) :
BaseMusicAdapter<Track>(items, activity, recyclerView, itemClick), ItemTouchHelperContract, RecyclerViewFastScroller.OnPopupTextUpdate {
@ -46,7 +43,10 @@ class QueueAdapter(activity: SimpleActivity, items: ArrayList<Track>, var curren
override fun getActionMenuId() = R.menu.cab_queue
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_track_queue, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemTrackQueueBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items.getOrNull(position) ?: return
@ -75,7 +75,7 @@ class QueueAdapter(activity: SimpleActivity, items: ArrayList<Track>, var curren
override fun onActionModeDestroyed() = notifyDataChanged()
fun updateCurrentTrack() {
ctx.withPlayer {
context.withPlayer {
val track = currentMediaItem?.toTrack()
if (track != null) {
val lastTrackId = currentTrack?.mediaStoreId
@ -101,13 +101,13 @@ class QueueAdapter(activity: SimpleActivity, items: ArrayList<Track>, var curren
}
}
ctx.removeQueueItems(selectedTracks) {
context.removeQueueItems(selectedTracks) {
refreshTracksList(positions)
}
}
private fun deleteTracks() {
ConfirmationDialog(ctx, "", R.string.delete_song_warning, R.string.ok, R.string.cancel) {
ConfirmationDialog(context, "", R.string.delete_song_warning, com.simplemobiletools.commons.R.string.ok, com.simplemobiletools.commons.R.string.cancel) {
val positions = ArrayList<Int>()
val selectedTracks = getSelectedTracks()
selectedTracks.forEach { track ->
@ -117,14 +117,14 @@ class QueueAdapter(activity: SimpleActivity, items: ArrayList<Track>, var curren
}
}
ctx.deleteTracks(selectedTracks) {
context.deleteTracks(selectedTracks) {
refreshTracksList(positions)
}
}
}
private fun refreshTracksList(positions: ArrayList<Int>) {
ctx.runOnUiThread {
context.runOnUiThread {
positions.sortDescending()
positions.forEach {
items.removeAt(it)
@ -132,41 +132,45 @@ class QueueAdapter(activity: SimpleActivity, items: ArrayList<Track>, var curren
removeSelectedItems(positions)
if (items.isEmpty()) {
ctx.finish()
context.finish()
}
}
}
@SuppressLint("ClickableViewAccessibility")
private fun setupView(view: View, track: Track, holder: ViewHolder) {
view.apply {
setupViewBackground(ctx)
track_queue_frame?.isSelected = selectedKeys.contains(track.hashCode())
track_queue_title.text = if (textToHighlight.isEmpty()) track.title else track.title.highlightTextPart(textToHighlight, properPrimaryColor)
ItemTrackQueueBinding.bind(view).apply {
root.setupViewBackground(context)
trackQueueFrame.isSelected = selectedKeys.contains(track.hashCode())
trackQueueTitle.text = if (textToHighlight.isEmpty()) track.title else track.title.highlightTextPart(textToHighlight, properPrimaryColor)
arrayOf(track_queue_title, track_queue_duration).forEach {
val color = if (track.mediaStoreId == currentTrack?.mediaStoreId) context.getProperPrimaryColor() else textColor
arrayOf(trackQueueTitle, trackQueueDuration).forEach {
val color = if (track.mediaStoreId == currentTrack?.mediaStoreId) {
activity.getProperPrimaryColor()
} else {
textColor
}
it.setTextColor(color)
}
track_queue_duration.text = track.duration.getFormattedDuration()
track_queue_drag_handle.beVisibleIf(selectedKeys.isNotEmpty())
track_queue_drag_handle.applyColorFilter(textColor)
track_queue_drag_handle.setOnTouchListener { _, event ->
trackQueueDuration.text = track.duration.getFormattedDuration()
trackQueueDragHandle.beVisibleIf(selectedKeys.isNotEmpty())
trackQueueDragHandle.applyColorFilter(textColor)
trackQueueDragHandle.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
startReorderDragListener.requestDrag(holder)
}
false
}
ctx.getTrackCoverArt(track) { coverArt ->
loadImage(findViewById(R.id.track_queue_image), coverArt, placeholderBig)
context.getTrackCoverArt(track) { coverArt ->
loadImage(trackQueueImage, coverArt, placeholderBig)
}
}
}
override fun updateItems(newItems: ArrayList<Track>, highlightText: String, forceUpdate: Boolean) {
ctx.withPlayer {
context.withPlayer {
currentTrack = currentMediaItem?.toTrack()
super.updateItems(newItems, highlightText, forceUpdate)
}
@ -182,14 +186,14 @@ class QueueAdapter(activity: SimpleActivity, items: ArrayList<Track>, var curren
override fun onRowSelected(myViewHolder: ViewHolder?) {}
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(ctx.config.trackSorting) ?: ""
override fun onChange(position: Int) = items.getOrNull(position)?.getBubbleText(context.config.trackSorting) ?: ""
/**
* [MediaController.moveMediaItem] is the proper way to move media items but it doesn't work when shuffle mode is enabled. This method modifies
* the shuffle order when shuffle mode is enabled and defaults to [MediaController.moveMediaItem] otherwise.
*/
private fun swapMediaItemInQueue(fromPosition: Int, toPosition: Int) {
ctx.withPlayer {
context.withPlayer {
if (shuffleModeEnabled) {
val indices = shuffledMediaItemsIndices.toMutableList()
indices.swap(fromPosition, toPosition)

View file

@ -17,6 +17,7 @@ import com.simplemobiletools.commons.interfaces.ItemTouchHelperContract
import com.simplemobiletools.commons.interfaces.StartReorderDragListener
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.ItemTrackBinding
import com.simplemobiletools.musicplayer.dialogs.EditDialog
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.helpers.ALL_TRACKS_PLAYLIST_ID
@ -25,7 +26,6 @@ import com.simplemobiletools.musicplayer.inlines.indexOfFirstOrNull
import com.simplemobiletools.musicplayer.models.Events
import com.simplemobiletools.musicplayer.models.Playlist
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.item_track.view.*
import org.greenrobot.eventbus.EventBus
class TracksAdapter(
@ -42,8 +42,6 @@ class TracksAdapter(
private var startReorderDragListener: StartReorderDragListener
init {
setupDragListener(true)
touchHelper = ItemTouchHelper(ItemMoveCallback(this))
touchHelper!!.attachToRecyclerView(recyclerView)
@ -56,7 +54,10 @@ class TracksAdapter(
override fun getActionMenuId() = R.menu.cab_tracks
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_track, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemTrackBinding.inflate(layoutInflater, parent, false)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val track = items.getOrNull(position) ?: return
@ -115,18 +116,18 @@ class TracksAdapter(
}
}
ctx.audioHelper.deleteTracks(selectedTracks)
context.audioHelper.deleteTracks(selectedTracks)
// this is to make sure these tracks aren't automatically re-added to the 'All tracks' playlist on rescan
val removedTrackIds = selectedTracks.filter { it.playListId == ALL_TRACKS_PLAYLIST_ID }.map { it.mediaStoreId.toString() }
if (removedTrackIds.isNotEmpty()) {
val config = ctx.config
val config = context.config
config.tracksRemovedFromAllTracksPlaylist = config.tracksRemovedFromAllTracksPlaylist.apply {
addAll(removedTrackIds)
}
}
EventBus.getDefault().post(Events.PlaylistsUpdated())
ctx.runOnUiThread {
context.runOnUiThread {
positions.sortDescending()
removeSelectedItems(positions)
positions.forEach {
@ -137,7 +138,7 @@ class TracksAdapter(
}
private fun askConfirmDelete() {
ConfirmationDialog(ctx) {
ConfirmationDialog(context) {
ensureBackgroundThread {
val positions = ArrayList<Int>()
val selectedTracks = getSelectedTracks()
@ -148,8 +149,8 @@ class TracksAdapter(
}
}
ctx.deleteTracks(selectedTracks) {
ctx.runOnUiThread {
context.deleteTracks(selectedTracks) {
context.runOnUiThread {
positions.sortDescending()
removeSelectedItems(positions)
positions.forEach {
@ -162,7 +163,7 @@ class TracksAdapter(
// finish activity if all tracks are deleted
if (items.isEmpty() && !isPlaylistContent()) {
ctx.finish()
context.finish()
}
}
}
@ -174,45 +175,45 @@ class TracksAdapter(
@SuppressLint("ClickableViewAccessibility")
private fun setupView(view: View, track: Track, holder: ViewHolder) {
view.apply {
setupViewBackground(ctx)
track_frame?.isSelected = selectedKeys.contains(track.hashCode())
track_title.text = if (textToHighlight.isEmpty()) track.title else track.title.highlightTextPart(textToHighlight, properPrimaryColor)
track_info.text = if (textToHighlight.isEmpty()) {
ItemTrackBinding.bind(view).apply {
root.setupViewBackground(context)
trackFrame.isSelected = selectedKeys.contains(track.hashCode())
trackTitle.text = if (textToHighlight.isEmpty()) track.title else track.title.highlightTextPart(textToHighlight, properPrimaryColor)
trackInfo.text = if (textToHighlight.isEmpty()) {
"${track.artist}${track.album}"
} else {
("${track.artist}${track.album}").highlightTextPart(textToHighlight, properPrimaryColor)
}
track_drag_handle.beVisibleIf(isPlaylistContent() && selectedKeys.isNotEmpty())
track_drag_handle.applyColorFilter(textColor)
track_drag_handle.setOnTouchListener { _, event ->
trackDragHandle.beVisibleIf(isPlaylistContent() && selectedKeys.isNotEmpty())
trackDragHandle.applyColorFilter(textColor)
trackDragHandle.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
startReorderDragListener.requestDrag(holder)
}
false
}
arrayOf(track_id, track_title, track_info, track_duration).forEach {
arrayOf(trackId, trackTitle, trackInfo, trackDuration).forEach {
it.setTextColor(textColor)
}
track_duration.text = track.duration.getFormattedDuration()
context.getTrackCoverArt(track) { coverArt ->
loadImage(findViewById(R.id.track_image), coverArt, placeholderBig)
trackDuration.text = track.duration.getFormattedDuration()
activity.getTrackCoverArt(track) { coverArt ->
loadImage(trackImage, coverArt, placeholderBig)
}
track_image.beVisible()
track_id.beGone()
trackImage.beVisible()
trackId.beGone()
}
}
override fun onChange(position: Int): String {
val sorting = if (isPlaylistContent() && playlist != null) {
ctx.config.getProperPlaylistSorting(playlist.id)
context.config.getProperPlaylistSorting(playlist.id)
} else if (sourceType == TYPE_FOLDER && folder != null) {
ctx.config.getProperFolderSorting(folder)
context.config.getProperFolderSorting(folder)
} else {
ctx.config.trackSorting
context.config.trackSorting
}
return items.getOrNull(position)?.getBubbleText(sorting) ?: ""
@ -220,19 +221,19 @@ class TracksAdapter(
private fun displayEditDialog() {
getSelectedTracks().firstOrNull()?.let { selectedTrack ->
EditDialog(ctx, selectedTrack) { track ->
EditDialog(context, selectedTrack) { track ->
val trackIndex = items.indexOfFirstOrNull { it.mediaStoreId == track.mediaStoreId } ?: return@EditDialog
items[trackIndex] = track
notifyItemChanged(trackIndex)
finishActMode()
ctx.refreshQueueAndTracks(track)
context.refreshQueueAndTracks(track)
}
}
}
override fun onRowMoved(fromPosition: Int, toPosition: Int) {
ctx.config.saveCustomPlaylistSorting(playlist!!.id, PLAYER_SORT_BY_CUSTOM)
context.config.saveCustomPlaylistSorting(playlist!!.id, PLAYER_SORT_BY_CUSTOM)
items.swap(fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
}
@ -244,7 +245,7 @@ class TracksAdapter(
var index = 0
items.forEach {
it.orderInPlaylist = index++
ctx.audioHelper.updateOrderInPlaylist(index, it.id)
context.audioHelper.updateOrderInPlaylist(index, it.id)
}
}
}

View file

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.beGone
@ -15,15 +14,13 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.databinding.ItemAlbumHeaderBinding
import com.simplemobiletools.musicplayer.databinding.ItemTrackBinding
import com.simplemobiletools.musicplayer.dialogs.EditDialog
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.models.AlbumHeader
import com.simplemobiletools.musicplayer.models.ListItem
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.item_album_header.view.album_artist
import kotlinx.android.synthetic.main.item_album_header.view.album_meta
import kotlinx.android.synthetic.main.item_album_header.view.album_title
import kotlinx.android.synthetic.main.item_track.view.*
class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) :
BaseMusicAdapter<ListItem>(items, activity, recyclerView, itemClick), RecyclerViewFastScroller.OnPopupTextUpdate {
@ -31,17 +28,17 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
private val ITEM_HEADER = 0
private val ITEM_TRACK = 1
override val cornerRadius = resources.getDimension(R.dimen.rounded_corner_radius_big).toInt()
override val cornerRadius = resources.getDimension(com.simplemobiletools.commons.R.dimen.rounded_corner_radius_big).toInt()
override fun getActionMenuId() = R.menu.cab_tracks_header
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layout = when (viewType) {
ITEM_HEADER -> R.layout.item_album_header
else -> R.layout.item_track
val binding = when (viewType) {
ITEM_HEADER -> ItemAlbumHeaderBinding.inflate(layoutInflater, parent, false)
else -> ItemTrackBinding.inflate(layoutInflater, parent, false)
}
return createViewHolder(layout, parent)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@ -92,7 +89,7 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
override fun getIsItemSelectable(position: Int) = position != 0
private fun askConfirmDelete() {
ConfirmationDialog(ctx) {
ConfirmationDialog(context) {
ensureBackgroundThread {
val positions = ArrayList<Int>()
val selectedTracks = getSelectedTracks()
@ -103,8 +100,8 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
}
}
ctx.deleteTracks(selectedTracks) {
ctx.runOnUiThread {
context.deleteTracks(selectedTracks) {
context.runOnUiThread {
positions.sortDescending()
removeSelectedItems(positions)
positions.forEach {
@ -113,7 +110,7 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
// finish activity if all tracks are deleted
if (items.none { it is Track }) {
ctx.finish()
context.finish()
}
}
}
@ -122,27 +119,27 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
}
private fun setupTrack(view: View, track: Track) {
view.apply {
setupViewBackground(ctx)
track_frame?.isSelected = selectedKeys.contains(track.hashCode())
track_title.text = track.title
track_info.beGone()
ItemTrackBinding.bind(view).apply {
root.setupViewBackground(context)
trackFrame.isSelected = selectedKeys.contains(track.hashCode())
trackTitle.text = track.title
trackInfo.beGone()
arrayOf(track_id, track_title, track_duration).forEach {
arrayOf(trackId, trackTitle, trackDuration).forEach {
it.setTextColor(textColor)
}
track_duration.text = track.duration.getFormattedDuration()
track_id.text = track.trackId.toString()
track_image.beGone()
track_id.beVisible()
trackDuration.text = track.duration.getFormattedDuration()
trackId.text = track.trackId.toString()
trackImage.beGone()
trackId.beVisible()
}
}
private fun setupHeader(view: View, header: AlbumHeader) {
view.apply {
album_title.text = header.title
album_artist.text = header.artist
ItemAlbumHeaderBinding.bind(view).apply {
albumTitle.text = header.title
albumArtist.text = header.artist
val tracks = resources.getQuantityString(R.plurals.tracks_plural, header.trackCnt, header.trackCnt)
var year = ""
@ -151,21 +148,21 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
}
@SuppressLint("SetTextI18n")
album_meta.text = "$year$tracks${header.duration.getFormattedDuration(true)}"
albumMeta.text = "$year$tracks${header.duration.getFormattedDuration(true)}"
arrayOf(album_title, album_artist, album_meta).forEach {
arrayOf(albumTitle, albumArtist, albumMeta).forEach {
it.setTextColor(textColor)
}
ensureBackgroundThread {
val album = ctx.audioHelper.getAlbum(header.id)
val album = context.audioHelper.getAlbum(header.id)
if (album != null) {
ctx.getAlbumCoverArt(album) { coverArt ->
loadImage(findViewById(R.id.album_image), coverArt, placeholderBig)
context.getAlbumCoverArt(album) { coverArt ->
loadImage(albumImage, coverArt, placeholderBig)
}
} else {
ctx.runOnUiThread {
findViewById<ImageView>(R.id.album_image).setImageDrawable(placeholderBig)
context.runOnUiThread {
albumImage.setImageDrawable(placeholderBig)
}
}
}
@ -174,7 +171,7 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
override fun onChange(position: Int): CharSequence {
return when (val listItem = items.getOrNull(position)) {
is Track -> listItem.getBubbleText(ctx.config.trackSorting)
is Track -> listItem.getBubbleText(context.config.trackSorting)
is AlbumHeader -> listItem.title
else -> ""
}
@ -182,7 +179,7 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
private fun displayEditDialog() {
getSelectedTracks().firstOrNull()?.let { selectedTrack ->
EditDialog(ctx, selectedTrack) { track ->
EditDialog(context, selectedTrack) { track ->
val trackIndex = items.indexOfFirst { (it as? Track)?.mediaStoreId == track.mediaStoreId }
if (trackIndex != -1) {
items[trackIndex] = track
@ -190,7 +187,7 @@ class TracksHeaderAdapter(activity: SimpleActivity, items: ArrayList<ListItem>,
finishActMode()
}
ctx.refreshQueueAndTracks(track)
context.refreshQueueAndTracks(track)
}
}
}

View file

@ -5,62 +5,59 @@ import android.view.ViewGroup
import androidx.viewpager.widget.PagerAdapter
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.databinding.*
import com.simplemobiletools.musicplayer.extensions.getVisibleTabs
import com.simplemobiletools.musicplayer.fragments.MyViewPagerFragment
import com.simplemobiletools.musicplayer.fragments.PlaylistsFragment
import com.simplemobiletools.musicplayer.fragments.TracksFragment
import com.simplemobiletools.musicplayer.helpers.*
class ViewPagerAdapter(val activity: SimpleActivity) : PagerAdapter() {
val showTabs = activity.config.showTabs
private val fragments = arrayListOf<MyViewPagerFragment>()
private var primaryItem: MyViewPagerFragment? = null
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val layout = getFragment(position)
val view = activity.layoutInflater.inflate(layout, container, false)
container.addView(view)
(view as MyViewPagerFragment).apply {
return getFragment(position, container).apply {
fragments.add(this)
container.addView(this)
setupFragment(activity)
setupColors(activity.getProperTextColor(), activity.getProperPrimaryColor())
}
return view
}
override fun destroyItem(container: ViewGroup, position: Int, item: Any) {
fragments.remove(item)
container.removeView(item as View)
}
override fun getCount() = tabsList.filter { it and showTabs != 0 }.size
override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) {
primaryItem = `object` as MyViewPagerFragment
}
override fun getCount() = activity.getVisibleTabs().size
override fun isViewFromObject(view: View, item: Any) = view == item
private fun getFragment(position: Int): Int {
val fragments = arrayListOf<Int>()
if (showTabs and TAB_PLAYLISTS != 0) {
fragments.add(R.layout.fragment_playlists)
private fun getFragment(position: Int, container: ViewGroup): MyViewPagerFragment {
val tab = activity.getVisibleTabs()[position]
val layoutInflater = activity.layoutInflater
return when (tab) {
TAB_PLAYLISTS -> FragmentPlaylistsBinding.inflate(layoutInflater, container, false).root
TAB_FOLDERS -> FragmentFoldersBinding.inflate(layoutInflater, container, false).root
TAB_ARTISTS -> FragmentArtistsBinding.inflate(layoutInflater, container, false).root
TAB_ALBUMS -> FragmentAlbumsBinding.inflate(layoutInflater, container, false).root
TAB_TRACKS -> FragmentTracksBinding.inflate(layoutInflater, container, false).root
TAB_GENRES -> FragmentGenresBinding.inflate(layoutInflater, container, false).root
else -> throw IllegalArgumentException("Unknown tab: $tab")
}
if (showTabs and TAB_FOLDERS != 0) {
fragments.add(R.layout.fragment_folders)
}
if (showTabs and TAB_ARTISTS != 0) {
fragments.add(R.layout.fragment_artists)
}
if (showTabs and TAB_ALBUMS != 0) {
fragments.add(R.layout.fragment_albums)
}
if (showTabs and TAB_TRACKS != 0) {
fragments.add(R.layout.fragment_tracks)
}
if (showTabs and TAB_GENRES != 0) {
fragments.add(R.layout.fragment_genres)
}
return fragments[position]
}
fun getAllFragments() = fragments
fun getCurrentFragment() = primaryItem
fun getPlaylistsFragment() = fragments.find { it is PlaylistsFragment }
fun getTracksFragment() = fragments.find { it is TracksFragment }
}

View file

@ -1,36 +1,36 @@
package com.simplemobiletools.musicplayer.dialogs
import android.app.Activity
import android.view.View
import android.view.ViewGroup
import android.widget.RadioGroup
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.views.MyCompatRadioButton
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.DialogChangeSortingBinding
import com.simplemobiletools.musicplayer.databinding.SmallRadioButtonBinding
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.helpers.*
import com.simplemobiletools.musicplayer.models.Playlist
import kotlinx.android.synthetic.main.dialog_change_sorting.view.*
class ChangeSortingDialog(val activity: Activity, val location: Int, val playlist: Playlist? = null, val path: String? = null, val callback: () -> Unit) {
private val config = activity.config
private var currSorting = 0
private val view: View
private val binding by activity.viewBinding(DialogChangeSortingBinding::inflate)
init {
view = activity.layoutInflater.inflate(R.layout.dialog_change_sorting, null).apply {
use_for_this_playlist_divider.beVisibleIf(playlist != null || path != null)
sorting_dialog_use_for_this_only.beVisibleIf(playlist != null || path != null)
binding.apply {
useForThisPlaylistDivider.beVisibleIf(playlist != null || path != null)
sortingDialogUseForThisOnly.beVisibleIf(playlist != null || path != null)
if (playlist != null) {
sorting_dialog_use_for_this_only.isChecked = config.hasCustomPlaylistSorting(playlist.id)
sortingDialogUseForThisOnly.isChecked = config.hasCustomPlaylistSorting(playlist.id)
} else if (path != null) {
sorting_dialog_use_for_this_only.text = activity.getString(R.string.use_for_this_folder)
sorting_dialog_use_for_this_only.isChecked = config.hasCustomSorting(path)
sortingDialogUseForThisOnly.text = activity.getString(com.simplemobiletools.commons.R.string.use_for_this_folder)
sortingDialogUseForThisOnly.isChecked = config.hasCustomSorting(path)
}
}
@ -54,10 +54,10 @@ class ChangeSortingDialog(val activity: Activity, val location: Int, val playlis
setupOrderRadio()
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dialogConfirmed() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.sort_by)
activity.setupDialogStuff(binding.root, this, com.simplemobiletools.commons.R.string.sort_by)
}
}
@ -65,59 +65,64 @@ class ChangeSortingDialog(val activity: Activity, val location: Int, val playlis
val radioItems = ArrayList<RadioItem>()
when (location) {
TAB_PLAYLISTS, TAB_FOLDERS -> {
radioItems.add(RadioItem(0, activity.getString(R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(0, activity.getString(com.simplemobiletools.commons.R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(1, activity.getString(R.string.track_count), PLAYER_SORT_BY_TRACK_COUNT))
}
TAB_ARTISTS -> {
radioItems.add(RadioItem(0, activity.getString(R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(0, activity.getString(com.simplemobiletools.commons.R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(1, activity.getString(R.string.album_count), PLAYER_SORT_BY_ALBUM_COUNT))
radioItems.add(RadioItem(2, activity.getString(R.string.track_count), PLAYER_SORT_BY_TRACK_COUNT))
}
TAB_ALBUMS -> {
radioItems.add(RadioItem(0, activity.getString(R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(0, activity.getString(com.simplemobiletools.commons.R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(1, activity.getString(R.string.artist_name), PLAYER_SORT_BY_ARTIST_TITLE))
radioItems.add(RadioItem(2, activity.getString(R.string.year), PLAYER_SORT_BY_YEAR))
radioItems.add(RadioItem(4, activity.getString(R.string.date_added), PLAYER_SORT_BY_DATE_ADDED))
radioItems.add(RadioItem(4, activity.getString(com.simplemobiletools.commons.R.string.date_added), PLAYER_SORT_BY_DATE_ADDED))
}
TAB_TRACKS -> {
radioItems.add(RadioItem(0, activity.getString(R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(1, activity.getString(R.string.artist), PLAYER_SORT_BY_ARTIST_TITLE))
radioItems.add(RadioItem(2, activity.getString(R.string.duration), PLAYER_SORT_BY_DURATION))
radioItems.add(RadioItem(0, activity.getString(com.simplemobiletools.commons.R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(1, activity.getString(com.simplemobiletools.commons.R.string.artist), PLAYER_SORT_BY_ARTIST_TITLE))
radioItems.add(RadioItem(2, activity.getString(com.simplemobiletools.commons.R.string.duration), PLAYER_SORT_BY_DURATION))
radioItems.add(RadioItem(3, activity.getString(R.string.track_number), PLAYER_SORT_BY_TRACK_ID))
radioItems.add(RadioItem(4, activity.getString(R.string.date_added), PLAYER_SORT_BY_DATE_ADDED))
radioItems.add(RadioItem(4, activity.getString(com.simplemobiletools.commons.R.string.date_added), PLAYER_SORT_BY_DATE_ADDED))
}
TAB_GENRES -> {
radioItems.add(RadioItem(0, activity.getString(R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(0, activity.getString(com.simplemobiletools.commons.R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(2, activity.getString(R.string.track_count), PLAYER_SORT_BY_TRACK_COUNT))
}
ACTIVITY_PLAYLIST_FOLDER -> {
radioItems.add(RadioItem(0, activity.getString(R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(1, activity.getString(R.string.artist), PLAYER_SORT_BY_ARTIST_TITLE))
radioItems.add(RadioItem(2, activity.getString(R.string.duration), PLAYER_SORT_BY_DURATION))
radioItems.add(RadioItem(0, activity.getString(com.simplemobiletools.commons.R.string.title), PLAYER_SORT_BY_TITLE))
radioItems.add(RadioItem(1, activity.getString(com.simplemobiletools.commons.R.string.artist), PLAYER_SORT_BY_ARTIST_TITLE))
radioItems.add(RadioItem(2, activity.getString(com.simplemobiletools.commons.R.string.duration), PLAYER_SORT_BY_DURATION))
radioItems.add(RadioItem(3, activity.getString(R.string.track_number), PLAYER_SORT_BY_TRACK_ID))
radioItems.add(RadioItem(4, activity.getString(R.string.date_added), PLAYER_SORT_BY_DATE_ADDED))
radioItems.add(RadioItem(4, activity.getString(com.simplemobiletools.commons.R.string.date_added), PLAYER_SORT_BY_DATE_ADDED))
if (playlist != null) {
radioItems.add(RadioItem(4, activity.getString(R.string.custom), PLAYER_SORT_BY_CUSTOM))
radioItems.add(RadioItem(4, activity.getString(com.simplemobiletools.commons.R.string.custom), PLAYER_SORT_BY_CUSTOM))
}
}
}
view.sorting_dialog_radio_sorting.setOnCheckedChangeListener { group, checkedId ->
view.sorting_order_divider.beVisibleIf(checkedId != PLAYER_SORT_BY_CUSTOM)
view.sorting_dialog_radio_order.beVisibleIf(checkedId != PLAYER_SORT_BY_CUSTOM)
binding.sortingDialogRadioSorting.setOnCheckedChangeListener { _, checkedId ->
binding.sortingOrderDivider.beVisibleIf(checkedId != PLAYER_SORT_BY_CUSTOM)
binding.sortingDialogRadioOrder.beVisibleIf(checkedId != PLAYER_SORT_BY_CUSTOM)
}
radioItems.forEach { radioItem ->
activity.layoutInflater.inflate(R.layout.small_radio_button, null).apply {
findViewById<MyCompatRadioButton>(R.id.small_radio_button).apply {
SmallRadioButtonBinding.inflate(activity.layoutInflater).apply {
smallRadioButton.apply {
text = radioItem.title
isChecked = currSorting and (radioItem.value as Int) != 0
id = radioItem.value as Int
}
view.sorting_dialog_radio_sorting.addView(
this,
binding.sortingDialogRadioSorting.addView(
smallRadioButton,
RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
)
}
@ -125,21 +130,20 @@ class ChangeSortingDialog(val activity: Activity, val location: Int, val playlis
}
private fun setupOrderRadio() {
val orderRadio = view.sorting_dialog_radio_order
var orderBtn = orderRadio.sorting_dialog_radio_ascending
var orderBtn = binding.sortingDialogRadioAscending
if (currSorting and SORT_DESCENDING != 0) {
orderBtn = orderRadio.sorting_dialog_radio_descending
orderBtn = binding.sortingDialogRadioDescending
}
orderBtn.isChecked = true
}
private fun dialogConfirmed() {
val sortingRadio = view.sorting_dialog_radio_sorting
val sortingRadio = binding.sortingDialogRadioSorting
var sorting = sortingRadio.checkedRadioButtonId
if (view.sorting_dialog_radio_order.checkedRadioButtonId == R.id.sorting_dialog_radio_descending) {
if (binding.sortingDialogRadioOrder.checkedRadioButtonId == R.id.sorting_dialog_radio_descending) {
sorting = sorting or SORT_DESCENDING
}
@ -152,7 +156,7 @@ class ChangeSortingDialog(val activity: Activity, val location: Int, val playlis
TAB_TRACKS -> config.trackSorting = sorting
TAB_GENRES -> config.genreSorting = sorting
ACTIVITY_PLAYLIST_FOLDER -> {
if (view.sorting_dialog_use_for_this_only.isChecked) {
if (binding.sortingDialogUseForThisOnly.isChecked) {
if (playlist != null) {
config.saveCustomPlaylistSorting(playlist.id, sorting)
} else if (path != null) {

View file

@ -6,41 +6,42 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isRPlus
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.DialogRenameSongBinding
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.helpers.TagHelper
import com.simplemobiletools.musicplayer.models.Track
import kotlinx.android.synthetic.main.dialog_rename_song.view.*
class EditDialog(val activity: BaseSimpleActivity, val track: Track, val callback: (track: Track) -> Unit) {
private val tagHelper = TagHelper(activity)
private val binding by activity.viewBinding(DialogRenameSongBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_rename_song, null).apply {
binding.apply {
title.setText(track.title)
artist.setText(track.artist)
album.setText(track.album)
val filename = track.path.getFilenameFromPath()
file_name.setText(filename.substring(0, filename.lastIndexOf(".")))
fileName.setText(filename.substring(0, filename.lastIndexOf(".")))
extension.setText(track.path.getFilenameExtension())
if (isRPlus()) {
arrayOf(file_name_hint, extension_hint).forEach {
arrayOf(fileNameHint, extensionHint).forEach {
it.beGone()
}
}
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.rename_song) { alertDialog ->
alertDialog.showKeyboard(view.title)
activity.setupDialogStuff(binding.root, this, R.string.rename_song) { alertDialog ->
alertDialog.showKeyboard(binding.title)
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val newTitle = view.title.value
val newArtist = view.artist.value
val newAlbum = view.album.value
val newFilename = view.file_name.value
val newFileExtension = view.extension.value
val newTitle = binding.title.value
val newArtist = binding.artist.value
val newAlbum = binding.album.value
val newFilename = binding.fileName.value
val newFileExtension = binding.extension.value
if (newTitle.isEmpty() || newArtist.isEmpty() || newFilename.isEmpty() || newFileExtension.isEmpty()) {
activity.toast(R.string.rename_song_empty)
@ -62,7 +63,7 @@ class EditDialog(val activity: BaseSimpleActivity, val track: Track, val callbac
}
if (!isRPlus()) {
activity.renameFile(oldPath, newPath, false) { success, andd ->
activity.renameFile(oldPath, newPath, false) { success, _ ->
if (success) {
storeEditedSong(track, oldPath, newPath)
track.path = newPath
@ -104,7 +105,7 @@ class EditDialog(val activity: BaseSimpleActivity, val track: Track, val callbac
}
}
} catch (e: Exception) {
activity.toast(R.string.unknown_error_occurred)
activity.toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
}
}

View file

@ -1,14 +1,13 @@
package com.simplemobiletools.musicplayer.dialogs
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.databinding.DialogExportPlaylistBinding
import com.simplemobiletools.musicplayer.extensions.config
import kotlinx.android.synthetic.main.dialog_export_playlist.view.*
import java.io.File
class ExportPlaylistDialog(
@ -18,23 +17,24 @@ class ExportPlaylistDialog(
private val callback: (file: File) -> Unit
) {
private var ignoreClicks = false
private var realPath = if (path.isEmpty()) activity.internalStoragePath else path
private var realPath = path.ifEmpty { activity.internalStoragePath }
private val binding by activity.viewBinding(DialogExportPlaylistBinding::inflate)
init {
val view = (activity.layoutInflater.inflate(R.layout.dialog_export_playlist, null) as ViewGroup).apply {
export_playlist_folder.text = activity.humanizePath(realPath)
binding.apply {
exportPlaylistFolder.text = activity.humanizePath(realPath)
val fileName = "playlist_${activity.getCurrentFormattedDateTime()}"
export_playlist_filename.setText(fileName)
exportPlaylistFilename.setText(fileName)
if (hidePath) {
export_playlist_folder_label.beGone()
export_playlist_folder.beGone()
exportPlaylistFolderLabel.beGone()
exportPlaylistFolder.beGone()
} else {
export_playlist_folder.setOnClickListener {
activity.hideKeyboard(export_playlist_filename)
exportPlaylistFolder.setOnClickListener {
activity.hideKeyboard(exportPlaylistFilename)
FilePickerDialog(activity, realPath, false, showFAB = true) {
export_playlist_folder.text = activity.humanizePath(it)
exportPlaylistFolder.text = activity.humanizePath(it)
realPath = it
}
}
@ -42,18 +42,18 @@ class ExportPlaylistDialog(
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.export_playlist) { alertDialog ->
activity.setupDialogStuff(binding.root, this, R.string.export_playlist) { alertDialog ->
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val filename = view.export_playlist_filename.value
val filename = binding.exportPlaylistFilename.value
when {
filename.isEmpty() -> activity.toast(R.string.empty_name)
filename.isEmpty() -> activity.toast(com.simplemobiletools.commons.R.string.empty_name)
filename.isAValidFilename() -> {
val file = File(realPath, "$filename.m3u")
if (!hidePath && file.exists()) {
activity.toast(R.string.name_taken)
activity.toast(com.simplemobiletools.commons.R.string.name_taken)
return@setOnClickListener
}
@ -64,7 +64,8 @@ class ExportPlaylistDialog(
alertDialog.dismiss()
}
}
else -> activity.toast(R.string.invalid_name)
else -> activity.toast(com.simplemobiletools.commons.R.string.invalid_name)
}
}
}

View file

@ -4,49 +4,49 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.beGone
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.commons.views.MyAppCompatCheckbox
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.DialogManageVisibleTabsBinding
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.helpers.*
import kotlinx.android.synthetic.main.dialog_manage_visible_tabs.view.manage_visible_tabs_folders
class ManageVisibleTabsDialog(val activity: BaseSimpleActivity, val callback: (result: Int) -> Unit) {
private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_tabs, null)
private val tabs = LinkedHashMap<Int, Int>()
private val binding by activity.viewBinding(DialogManageVisibleTabsBinding::inflate)
private val tabs = LinkedHashMap<Int, MyAppCompatCheckbox>()
init {
tabs.apply {
put(TAB_PLAYLISTS, R.id.manage_visible_tabs_playlists)
put(TAB_FOLDERS, R.id.manage_visible_tabs_folders)
put(TAB_ARTISTS, R.id.manage_visible_tabs_artists)
put(TAB_ALBUMS, R.id.manage_visible_tabs_albums)
put(TAB_TRACKS, R.id.manage_visible_tabs_tracks)
put(TAB_GENRES, R.id.manage_visible_tabs_genres)
put(TAB_PLAYLISTS, binding.manageVisibleTabsPlaylists)
put(TAB_FOLDERS, binding.manageVisibleTabsFolders)
put(TAB_ARTISTS, binding.manageVisibleTabsArtists)
put(TAB_ALBUMS, binding.manageVisibleTabsAlbums)
put(TAB_TRACKS, binding.manageVisibleTabsTracks)
put(TAB_GENRES, binding.manageVisibleTabsGenres)
}
if (!isQPlus()) {
tabs.remove(TAB_FOLDERS)
view.manage_visible_tabs_folders.beGone()
binding.manageVisibleTabsFolders.beGone()
}
val showTabs = activity.config.showTabs
for ((key, value) in tabs) {
view.findViewById<MyAppCompatCheckbox>(value).isChecked = showTabs and key != 0
value.isChecked = showTabs and key != 0
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dialogConfirmed() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this)
activity.setupDialogStuff(binding.root, this)
}
}
private fun dialogConfirmed() {
var result = 0
for ((key, value) in tabs) {
if (view.findViewById<MyAppCompatCheckbox>(value).isChecked) {
if (value.isChecked) {
result += key
}
}

View file

@ -5,32 +5,30 @@ import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.DialogNewPlaylistBinding
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.getPlaylistIdWithTitle
import com.simplemobiletools.musicplayer.models.Playlist
import kotlinx.android.synthetic.main.dialog_new_playlist.view.new_playlist_title
class NewPlaylistDialog(val activity: Activity, var playlist: Playlist? = null, val callback: (playlistId: Int) -> Unit) {
var isNewPlaylist = playlist == null
private var isNewPlaylist = playlist == null
private val binding by activity.viewBinding(DialogNewPlaylistBinding::inflate)
init {
if (playlist == null) {
playlist = Playlist(0, "")
}
val view = activity.layoutInflater.inflate(R.layout.dialog_new_playlist, null).apply {
new_playlist_title.setText(playlist!!.title)
}
binding.newPlaylistTitle.setText(playlist!!.title)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
val dialogTitle = if (isNewPlaylist) R.string.create_new_playlist else R.string.rename_playlist
activity.setupDialogStuff(view, this, dialogTitle) { alertDialog ->
alertDialog.showKeyboard(view.new_playlist_title)
activity.setupDialogStuff(binding.root, this, dialogTitle) { alertDialog ->
alertDialog.showKeyboard(binding.newPlaylistTitle)
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val title = view.new_playlist_title.value
val title = binding.newPlaylistTitle.value
ensureBackgroundThread {
val playlistIdWithTitle = activity.getPlaylistIdWithTitle(title)
var isPlaylistTitleTaken = isNewPlaylist && playlistIdWithTitle != -1
@ -39,7 +37,7 @@ class NewPlaylistDialog(val activity: Activity, var playlist: Playlist? = null,
}
if (title.isEmpty()) {
activity.toast(R.string.empty_name)
activity.toast(com.simplemobiletools.commons.R.string.empty_name)
return@ensureBackgroundThread
} else if (isPlaylistTitleTaken) {
activity.toast(R.string.playlist_name_exists)
@ -59,7 +57,7 @@ class NewPlaylistDialog(val activity: Activity, var playlist: Playlist? = null,
alertDialog.dismiss()
callback(eventTypeId)
} else {
activity.toast(R.string.unknown_error_occurred)
activity.toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
}
}

View file

@ -3,21 +3,21 @@ package com.simplemobiletools.musicplayer.dialogs
import android.app.Activity
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.DialogRemovePlaylistBinding
import com.simplemobiletools.musicplayer.models.Playlist
import kotlinx.android.synthetic.main.dialog_remove_playlist.view.*
class RemovePlaylistDialog(val activity: Activity, val playlist: Playlist? = null, val callback: (deleteFiles: Boolean) -> Unit) {
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_remove_playlist, null).apply {
remove_playlist_description.text = getDescriptionText()
}
private val binding by activity.viewBinding(DialogRemovePlaylistBinding::inflate)
init {
binding.removePlaylistDescription.text = getDescriptionText()
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> callback(view.remove_playlist_checkbox.isChecked) }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> callback(binding.removePlaylistCheckbox.isChecked) }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.remove_playlist)
activity.setupDialogStuff(binding.root, this, R.string.remove_playlist)
}
}

View file

@ -1,29 +1,27 @@
package com.simplemobiletools.musicplayer.dialogs
import android.app.Activity
import android.view.View
import android.view.ViewGroup
import android.widget.RadioGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.DialogSelectPlaylistBinding
import com.simplemobiletools.musicplayer.databinding.ItemSelectPlaylistBinding
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.models.Playlist
import kotlinx.android.synthetic.main.dialog_select_playlist.view.dialog_select_playlist_linear
import kotlinx.android.synthetic.main.dialog_select_playlist.view.dialog_select_playlist_new_radio
import kotlinx.android.synthetic.main.item_select_playlist.view.select_playlist_item_radio_button
class SelectPlaylistDialog(val activity: Activity, val callback: (playlistId: Int) -> Unit) {
private var dialog: AlertDialog? = null
private val binding by activity.viewBinding(DialogSelectPlaylistBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_select_playlist, null)
ensureBackgroundThread {
val playlists = activity.audioHelper.getAllPlaylists()
activity.runOnUiThread {
initDialog(playlists, view)
initDialog(playlists)
if (playlists.isEmpty()) {
showNewPlaylistDialog()
@ -31,17 +29,17 @@ class SelectPlaylistDialog(val activity: Activity, val callback: (playlistId: In
}
}
view.dialog_select_playlist_new_radio.setOnClickListener {
view.dialog_select_playlist_new_radio.isChecked = false
binding.dialogSelectPlaylistNewRadio.setOnClickListener {
binding.dialogSelectPlaylistNewRadio.isChecked = false
showNewPlaylistDialog()
}
}
private fun initDialog(playlists: ArrayList<Playlist>, view: View) {
private fun initDialog(playlists: ArrayList<Playlist>) {
playlists.forEach {
activity.layoutInflater.inflate(R.layout.item_select_playlist, null).apply {
ItemSelectPlaylistBinding.inflate(activity.layoutInflater).apply {
val playlist = it
select_playlist_item_radio_button.apply {
selectPlaylistItemRadioButton.apply {
text = playlist.title
isChecked = false
id = playlist.id
@ -52,15 +50,15 @@ class SelectPlaylistDialog(val activity: Activity, val callback: (playlistId: In
}
}
view.dialog_select_playlist_linear.addView(
this,
binding.dialogSelectPlaylistLinear.addView(
this.root,
RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
)
}
}
activity.getAlertDialogBuilder().apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}

View file

@ -4,28 +4,28 @@ import android.app.Activity
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.musicplayer.R
import kotlinx.android.synthetic.main.dialog_custom_sleep_timer_picker.view.*
import com.simplemobiletools.musicplayer.databinding.DialogCustomSleepTimerPickerBinding
class SleepTimerCustomDialog(val activity: Activity, val callback: (seconds: Int) -> Unit) {
private var dialog: AlertDialog? = null
private val view = activity.layoutInflater.inflate(R.layout.dialog_custom_sleep_timer_picker, null)
private val binding by activity.viewBinding(DialogCustomSleepTimerPickerBinding::inflate)
init {
view.minutes_hint.hint = activity.getString(R.string.minutes_raw).replaceFirstChar { it.uppercaseChar() }
binding.minutesHint.hint = activity.getString(com.simplemobiletools.commons.R.string.minutes_raw).replaceFirstChar { it.uppercaseChar() }
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dialogConfirmed() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.sleep_timer) { alertDialog ->
activity.setupDialogStuff(binding.root, this, R.string.sleep_timer) { alertDialog ->
dialog = alertDialog
alertDialog.showKeyboard(view.minutes)
alertDialog.showKeyboard(binding.minutes)
}
}
}
private fun dialogConfirmed() {
val value = view.minutes.value
val minutes = Integer.valueOf(if (value.isEmpty()) "0" else value)
val value = binding.minutes.value
val minutes = Integer.valueOf(value.ifEmpty { "0" })
callback(minutes * 60)
activity.hideKeyboard()
dialog?.dismiss()

View file

@ -242,16 +242,16 @@ fun Context.loadGlideResource(
.load(model)
.apply(options)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>, isFirstResource: Boolean): Boolean {
onLoadFailed(e)
return true
}
override fun onResourceReady(
resource: Drawable,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
model: Any,
target: Target<Drawable>,
dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
onResourceReady(resource)
@ -266,13 +266,19 @@ fun Context.loadGlideResource(
}
}
fun Context.getTrackFromUri(uri: Uri?, callback: (track: Track) -> Unit) {
fun Context.getTrackFromUri(uri: Uri?, callback: (track: Track?) -> Unit) {
if (uri == null) {
callback(null)
return
}
ensureBackgroundThread {
val path = getRealPathFromURI(uri) ?: return@ensureBackgroundThread
val path = getRealPathFromURI(uri)
if (path == null) {
callback(null)
return@ensureBackgroundThread
}
val allTracks = audioHelper.getAllTracks()
val track = allTracks.find { it.path == path } ?: RoomHelper(this).getTrackFromPath(path) ?: return@ensureBackgroundThread
callback(track)
@ -281,6 +287,8 @@ fun Context.getTrackFromUri(uri: Uri?, callback: (track: Track) -> Unit) {
fun Context.isTabVisible(flag: Int) = config.showTabs and flag != 0
fun Context.getVisibleTabs() = tabsList.filter { isTabVisible(it) }
fun Context.getPlaybackSetting(repeatMode: @Player.RepeatMode Int): PlaybackSetting {
return when (repeatMode) {
Player.REPEAT_MODE_OFF -> PlaybackSetting.REPEAT_OFF

View file

@ -17,11 +17,11 @@ fun LottieAnimationView.updatePlayPauseIcon(isPlaying: Boolean, color: Int) {
playAnimation()
}
addValueCallback(
KeyPath("**"),
LottieProperty.COLOR_FILTER,
{ PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) }
)
tag = isPlaying
}
addValueCallback(
KeyPath("**"),
LottieProperty.COLOR_FILTER
) { PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) }
}

View file

@ -0,0 +1,9 @@
package com.simplemobiletools.musicplayer.extensions
import android.view.View
import androidx.viewbinding.ViewBinding
inline fun <T : ViewBinding> View.viewBinding(crossinline bind: (View) -> T) =
lazy(LazyThreadSafetyMode.NONE) {
bind(this)
}

View file

@ -5,7 +5,6 @@ import android.content.Intent
import android.util.AttributeSet
import com.google.gson.Gson
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.areSystemAnimationsEnabled
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.beVisibleIf
@ -15,21 +14,21 @@ import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.activities.TracksActivity
import com.simplemobiletools.musicplayer.adapters.AlbumsAdapter
import com.simplemobiletools.musicplayer.databinding.FragmentAlbumsBinding
import com.simplemobiletools.musicplayer.dialogs.ChangeSortingDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.mediaScanner
import com.simplemobiletools.musicplayer.extensions.viewBinding
import com.simplemobiletools.musicplayer.helpers.ALBUM
import com.simplemobiletools.musicplayer.helpers.TAB_ALBUMS
import com.simplemobiletools.musicplayer.models.Album
import com.simplemobiletools.musicplayer.models.sortSafely
import kotlinx.android.synthetic.main.fragment_albums.view.albums_fastscroller
import kotlinx.android.synthetic.main.fragment_albums.view.albums_list
import kotlinx.android.synthetic.main.fragment_albums.view.albums_placeholder
// Artists -> Albums -> Tracks
class AlbumsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
private var albums = ArrayList<Album>()
private val binding by viewBinding(FragmentAlbumsBinding::bind)
override fun setupFragment(activity: BaseSimpleActivity) {
ensureBackgroundThread {
@ -45,27 +44,27 @@ class AlbumsFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
activity.runOnUiThread {
val scanning = activity.mediaScanner.isScanning()
albums_placeholder.text = if (scanning) {
binding.albumsPlaceholder.text = if (scanning) {
context.getString(R.string.loading_files)
} else {
context.getString(R.string.no_items_found)
context.getString(com.simplemobiletools.commons.R.string.no_items_found)
}
albums_placeholder.beVisibleIf(albums.isEmpty())
binding.albumsPlaceholder.beVisibleIf(albums.isEmpty())
val adapter = albums_list.adapter
val adapter = binding.albumsList.adapter
if (adapter == null) {
AlbumsAdapter(activity, albums, albums_list) {
AlbumsAdapter(activity, albums, binding.albumsList) {
activity.hideKeyboard()
Intent(activity, TracksActivity::class.java).apply {
putExtra(ALBUM, Gson().toJson(it))
activity.startActivity(this)
}
}.apply {
albums_list.adapter = this
binding.albumsList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
albums_list.scheduleLayoutAnimation()
binding.albumsList.scheduleLayoutAnimation()
}
} else {
val oldItems = (adapter as AlbumsAdapter).items
@ -77,30 +76,33 @@ class AlbumsFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
}
override fun finishActMode() {
(albums_list.adapter as? MyRecyclerViewAdapter)?.finishActMode()
getAdapter()?.finishActMode()
}
override fun onSearchQueryChanged(text: String) {
val filtered = albums.filter { it.title.contains(text, true) }.toMutableList() as ArrayList<Album>
(albums_list.adapter as? AlbumsAdapter)?.updateItems(filtered, text)
albums_placeholder.beVisibleIf(filtered.isEmpty())
getAdapter()?.updateItems(filtered, text)
binding.albumsPlaceholder.beVisibleIf(filtered.isEmpty())
}
override fun onSearchClosed() {
(albums_list.adapter as? AlbumsAdapter)?.updateItems(albums)
albums_placeholder.beGoneIf(albums.isNotEmpty())
getAdapter()?.updateItems(albums)
binding.albumsPlaceholder.beGoneIf(albums.isNotEmpty())
}
override fun onSortOpen(activity: SimpleActivity) {
ChangeSortingDialog(activity, TAB_ALBUMS) {
val adapter = albums_list.adapter as? AlbumsAdapter ?: return@ChangeSortingDialog
val adapter = getAdapter() ?: return@ChangeSortingDialog
albums.sortSafely(activity.config.albumSorting)
adapter.updateItems(albums, forceUpdate = true)
}
}
override fun setupColors(textColor: Int, adjustedPrimaryColor: Int) {
albums_placeholder.setTextColor(textColor)
albums_fastscroller.updateColors(adjustedPrimaryColor)
binding.albumsPlaceholder.setTextColor(textColor)
binding.albumsFastscroller.updateColors(adjustedPrimaryColor)
getAdapter()?.updateColors(textColor)
}
private fun getAdapter() = binding.albumsList.adapter as? AlbumsAdapter
}

View file

@ -5,7 +5,6 @@ import android.content.Intent
import android.util.AttributeSet
import com.google.gson.Gson
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.areSystemAnimationsEnabled
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.beVisibleIf
@ -15,21 +14,21 @@ import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.AlbumsActivity
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.adapters.ArtistsAdapter
import com.simplemobiletools.musicplayer.databinding.FragmentArtistsBinding
import com.simplemobiletools.musicplayer.dialogs.ChangeSortingDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.mediaScanner
import com.simplemobiletools.musicplayer.extensions.viewBinding
import com.simplemobiletools.musicplayer.helpers.ARTIST
import com.simplemobiletools.musicplayer.helpers.TAB_ARTISTS
import com.simplemobiletools.musicplayer.models.Artist
import com.simplemobiletools.musicplayer.models.sortSafely
import kotlinx.android.synthetic.main.fragment_artists.view.artists_fastscroller
import kotlinx.android.synthetic.main.fragment_artists.view.artists_list
import kotlinx.android.synthetic.main.fragment_artists.view.artists_placeholder
// Artists -> Albums -> Tracks
class ArtistsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
private var artists = ArrayList<Artist>()
private val binding by viewBinding(FragmentArtistsBinding::bind)
override fun setupFragment(activity: BaseSimpleActivity) {
ensureBackgroundThread {
@ -44,27 +43,27 @@ class ArtistsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
artists = cachedArtists
activity.runOnUiThread {
val scanning = activity.mediaScanner.isScanning()
artists_placeholder.text = if (scanning) {
binding.artistsPlaceholder.text = if (scanning) {
context.getString(R.string.loading_files)
} else {
context.getString(R.string.no_items_found)
context.getString(com.simplemobiletools.commons.R.string.no_items_found)
}
artists_placeholder.beVisibleIf(artists.isEmpty())
binding.artistsPlaceholder.beVisibleIf(artists.isEmpty())
val adapter = artists_list.adapter
val adapter = binding.artistsList.adapter
if (adapter == null) {
ArtistsAdapter(activity, artists, artists_list) {
ArtistsAdapter(activity, artists, binding.artistsList) {
activity.hideKeyboard()
Intent(activity, AlbumsActivity::class.java).apply {
putExtra(ARTIST, Gson().toJson(it as Artist))
activity.startActivity(this)
}
}.apply {
artists_list.adapter = this
binding.artistsList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
artists_list.scheduleLayoutAnimation()
binding.artistsList.scheduleLayoutAnimation()
}
} else {
val oldItems = (adapter as ArtistsAdapter).items
@ -76,30 +75,33 @@ class ArtistsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
}
override fun finishActMode() {
(artists_list.adapter as? MyRecyclerViewAdapter)?.finishActMode()
getAdapter()?.finishActMode()
}
override fun onSearchQueryChanged(text: String) {
val filtered = artists.filter { it.title.contains(text, true) }.toMutableList() as ArrayList<Artist>
(artists_list.adapter as? ArtistsAdapter)?.updateItems(filtered, text)
artists_placeholder.beVisibleIf(filtered.isEmpty())
getAdapter()?.updateItems(filtered, text)
binding.artistsPlaceholder.beVisibleIf(filtered.isEmpty())
}
override fun onSearchClosed() {
(artists_list.adapter as? ArtistsAdapter)?.updateItems(artists)
artists_placeholder.beGoneIf(artists.isNotEmpty())
getAdapter()?.updateItems(artists)
binding.artistsPlaceholder.beGoneIf(artists.isNotEmpty())
}
override fun onSortOpen(activity: SimpleActivity) {
ChangeSortingDialog(activity, TAB_ARTISTS) {
val adapter = artists_list.adapter as? ArtistsAdapter ?: return@ChangeSortingDialog
val adapter = getAdapter() ?: return@ChangeSortingDialog
artists.sortSafely(activity.config.artistSorting)
adapter.updateItems(artists, forceUpdate = true)
}
}
override fun setupColors(textColor: Int, adjustedPrimaryColor: Int) {
artists_placeholder.setTextColor(textColor)
artists_fastscroller.updateColors(adjustedPrimaryColor)
binding.artistsPlaceholder.setTextColor(textColor)
binding.artistsFastscroller.updateColors(adjustedPrimaryColor)
getAdapter()?.updateColors(textColor)
}
private fun getAdapter() = binding.artistsList.adapter as? ArtistsAdapter
}

View file

@ -4,7 +4,6 @@ import android.content.Context
import android.content.Intent
import android.util.AttributeSet
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
@ -12,21 +11,20 @@ import com.simplemobiletools.musicplayer.activities.ExcludedFoldersActivity
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.activities.TracksActivity
import com.simplemobiletools.musicplayer.adapters.FoldersAdapter
import com.simplemobiletools.musicplayer.databinding.FragmentFoldersBinding
import com.simplemobiletools.musicplayer.dialogs.ChangeSortingDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.mediaScanner
import com.simplemobiletools.musicplayer.extensions.viewBinding
import com.simplemobiletools.musicplayer.helpers.FOLDER
import com.simplemobiletools.musicplayer.helpers.TAB_FOLDERS
import com.simplemobiletools.musicplayer.models.Folder
import com.simplemobiletools.musicplayer.models.sortSafely
import kotlinx.android.synthetic.main.fragment_folders.view.folders_fastscroller
import kotlinx.android.synthetic.main.fragment_folders.view.folders_list
import kotlinx.android.synthetic.main.fragment_folders.view.folders_placeholder
import kotlinx.android.synthetic.main.fragment_folders.view.folders_placeholder_2
class FoldersFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
private var folders = ArrayList<Folder>()
private val binding by viewBinding(FragmentFoldersBinding::bind)
override fun setupFragment(activity: BaseSimpleActivity) {
ensureBackgroundThread {
@ -34,36 +32,36 @@ class FoldersFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
activity.runOnUiThread {
val scanning = activity.mediaScanner.isScanning()
folders_placeholder.text = if (scanning) {
binding.foldersPlaceholder.text = if (scanning) {
context.getString(R.string.loading_files)
} else {
context.getString(R.string.no_items_found)
context.getString(com.simplemobiletools.commons.R.string.no_items_found)
}
folders_placeholder.beVisibleIf(folders.isEmpty())
folders_fastscroller.beGoneIf(folders_placeholder.isVisible())
folders_placeholder_2.beVisibleIf(folders.isEmpty() && context.config.excludedFolders.isNotEmpty() && !scanning)
folders_placeholder_2.underlineText()
binding.foldersPlaceholder.beVisibleIf(folders.isEmpty())
binding.foldersFastscroller.beGoneIf(binding.foldersPlaceholder.isVisible())
binding.foldersPlaceholder2.beVisibleIf(folders.isEmpty() && context.config.excludedFolders.isNotEmpty() && !scanning)
binding.foldersPlaceholder2.underlineText()
folders_placeholder_2.setOnClickListener {
binding.foldersPlaceholder2.setOnClickListener {
activity.startActivity(Intent(activity, ExcludedFoldersActivity::class.java))
}
this.folders = folders
val adapter = folders_list.adapter
val adapter = binding.foldersList.adapter
if (adapter == null) {
FoldersAdapter(activity, folders, folders_list) {
FoldersAdapter(activity, folders, binding.foldersList) {
activity.hideKeyboard()
Intent(activity, TracksActivity::class.java).apply {
putExtra(FOLDER, (it as Folder).title)
activity.startActivity(this)
}
}.apply {
folders_list.adapter = this
binding.foldersList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
folders_list.scheduleLayoutAnimation()
binding.foldersList.scheduleLayoutAnimation()
}
} else {
(adapter as FoldersAdapter).updateItems(folders)
@ -73,31 +71,34 @@ class FoldersFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
}
override fun finishActMode() {
(folders_list.adapter as? MyRecyclerViewAdapter)?.finishActMode()
getAdapter()?.finishActMode()
}
override fun onSearchQueryChanged(text: String) {
val filtered = folders.filter { it.title.contains(text, true) }.toMutableList() as ArrayList<Folder>
(folders_list.adapter as? FoldersAdapter)?.updateItems(filtered, text)
folders_placeholder.beVisibleIf(filtered.isEmpty())
getAdapter()?.updateItems(filtered, text)
binding.foldersPlaceholder.beVisibleIf(filtered.isEmpty())
}
override fun onSearchClosed() {
(folders_list.adapter as? FoldersAdapter)?.updateItems(folders)
folders_placeholder.beGoneIf(folders.isNotEmpty())
getAdapter()?.updateItems(folders)
binding.foldersPlaceholder.beGoneIf(folders.isNotEmpty())
}
override fun onSortOpen(activity: SimpleActivity) {
ChangeSortingDialog(activity, TAB_FOLDERS) {
val adapter = folders_list.adapter as? FoldersAdapter ?: return@ChangeSortingDialog
val adapter = getAdapter() ?: return@ChangeSortingDialog
folders.sortSafely(activity.config.folderSorting)
adapter.updateItems(folders, forceUpdate = true)
}
}
override fun setupColors(textColor: Int, adjustedPrimaryColor: Int) {
folders_placeholder.setTextColor(textColor)
folders_fastscroller.updateColors(adjustedPrimaryColor)
folders_placeholder_2.setTextColor(adjustedPrimaryColor)
binding.foldersPlaceholder.setTextColor(textColor)
binding.foldersFastscroller.updateColors(adjustedPrimaryColor)
binding.foldersPlaceholder2.setTextColor(adjustedPrimaryColor)
getAdapter()?.updateColors(textColor)
}
private fun getAdapter() = binding.foldersList.adapter as? FoldersAdapter
}

View file

@ -5,7 +5,6 @@ import android.content.Intent
import android.util.AttributeSet
import com.google.gson.Gson
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.areSystemAnimationsEnabled
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.beVisibleIf
@ -15,20 +14,20 @@ import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.activities.TracksActivity
import com.simplemobiletools.musicplayer.adapters.GenresAdapter
import com.simplemobiletools.musicplayer.databinding.FragmentGenresBinding
import com.simplemobiletools.musicplayer.dialogs.ChangeSortingDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.mediaScanner
import com.simplemobiletools.musicplayer.extensions.viewBinding
import com.simplemobiletools.musicplayer.helpers.GENRE
import com.simplemobiletools.musicplayer.helpers.TAB_GENRES
import com.simplemobiletools.musicplayer.models.Genre
import com.simplemobiletools.musicplayer.models.sortSafely
import kotlinx.android.synthetic.main.fragment_genres.view.genres_fastscroller
import kotlinx.android.synthetic.main.fragment_genres.view.genres_list
import kotlinx.android.synthetic.main.fragment_genres.view.genres_placeholder
class GenresFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
private var genres = ArrayList<Genre>()
private val binding by viewBinding(FragmentGenresBinding::bind)
override fun setupFragment(activity: BaseSimpleActivity) {
ensureBackgroundThread {
@ -43,27 +42,28 @@ class GenresFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
genres = cachedGenres
activity.runOnUiThread {
val scanning = activity.mediaScanner.isScanning()
genres_placeholder.text = if (scanning) {
binding.genresPlaceholder.text = if (scanning) {
context.getString(R.string.loading_files)
} else {
context.getString(R.string.no_items_found)
context.getString(com.simplemobiletools.commons.R.string.no_items_found)
}
genres_placeholder.beVisibleIf(genres.isEmpty())
val adapter = genres_list.adapter
binding.genresPlaceholder.beVisibleIf(genres.isEmpty())
val adapter = binding.genresList.adapter
if (adapter == null) {
GenresAdapter(activity, genres, genres_list) {
GenresAdapter(activity, genres, binding.genresList) {
activity.hideKeyboard()
Intent(activity, TracksActivity::class.java).apply {
putExtra(GENRE, Gson().toJson(it as Genre))
activity.startActivity(this)
}
}.apply {
genres_list.adapter = this
binding.genresList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
genres_list.scheduleLayoutAnimation()
binding.genresList.scheduleLayoutAnimation()
}
} else {
val oldItems = (adapter as GenresAdapter).items
@ -75,30 +75,33 @@ class GenresFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
}
override fun finishActMode() {
(genres_list.adapter as? MyRecyclerViewAdapter)?.finishActMode()
getAdapter()?.finishActMode()
}
override fun onSearchQueryChanged(text: String) {
val filtered = genres.filter { it.title.contains(text, true) }.toMutableList() as ArrayList<Genre>
(genres_list.adapter as? GenresAdapter)?.updateItems(filtered, text)
genres_placeholder.beVisibleIf(filtered.isEmpty())
getAdapter()?.updateItems(filtered, text)
binding.genresPlaceholder.beVisibleIf(filtered.isEmpty())
}
override fun onSearchClosed() {
(genres_list.adapter as? GenresAdapter)?.updateItems(genres)
genres_placeholder.beGoneIf(genres.isNotEmpty())
getAdapter()?.updateItems(genres)
binding.genresPlaceholder.beGoneIf(genres.isNotEmpty())
}
override fun onSortOpen(activity: SimpleActivity) {
ChangeSortingDialog(activity, TAB_GENRES) {
val adapter = genres_list.adapter as? GenresAdapter ?: return@ChangeSortingDialog
val adapter = getAdapter() ?: return@ChangeSortingDialog
genres.sortSafely(activity.config.genreSorting)
adapter.updateItems(genres, forceUpdate = true)
}
}
override fun setupColors(textColor: Int, adjustedPrimaryColor: Int) {
genres_placeholder.setTextColor(textColor)
genres_fastscroller.updateColors(adjustedPrimaryColor)
binding.genresPlaceholder.setTextColor(textColor)
binding.genresFastscroller.updateColors(adjustedPrimaryColor)
getAdapter()?.updateColors(textColor)
}
private fun getAdapter() = binding.genresList.adapter as? GenresAdapter
}

View file

@ -5,15 +5,16 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.res.ResourcesCompat
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.views.MySeekBar
import com.simplemobiletools.commons.views.MyTextView
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.databinding.FragmentPlaybackSpeedBinding
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.helpers.Config
import com.simplemobiletools.musicplayer.interfaces.PlaybackSpeedListener
import kotlinx.android.synthetic.main.fragment_playback_speed.view.*
class PlaybackSpeedFragment : BottomSheetDialogFragment() {
private val MIN_PLAYBACK_SPEED = 0.25f
@ -30,24 +31,25 @@ class PlaybackSpeedFragment : BottomSheetDialogFragment() {
setStyle(STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val config = requireContext().config
val view = inflater.inflate(R.layout.fragment_playback_speed, container, false)
val background = requireContext().resources.getDrawable(R.drawable.bottom_sheet_bg, requireContext().theme)
(background as LayerDrawable).findDrawableByLayerId(R.id.bottom_sheet_background).applyColorFilter(requireContext().getProperBackgroundColor())
val binding = FragmentPlaybackSpeedBinding.inflate(inflater, container, false)
val background = ResourcesCompat.getDrawable(resources, com.simplemobiletools.commons.R.drawable.bottom_sheet_bg, requireContext().theme)
(background as LayerDrawable).findDrawableByLayerId(com.simplemobiletools.commons.R.id.bottom_sheet_background)
.applyColorFilter(requireContext().getProperBackgroundColor())
view.apply {
seekBar = playback_speed_seekbar
setBackgroundDrawable(background)
requireContext().updateTextColors(playback_speed_holder)
playback_speed_slow.applyColorFilter(requireContext().getProperTextColor())
playback_speed_fast.applyColorFilter(requireContext().getProperTextColor())
playback_speed_slow.setOnClickListener { reduceSpeed() }
playback_speed_fast.setOnClickListener { increaseSpeed() }
initSeekbar(playback_speed_seekbar, playback_speed_label, config)
binding.apply {
seekBar = playbackSpeedSeekbar
root.setBackgroundDrawable(background)
requireContext().updateTextColors(playbackSpeedHolder)
playbackSpeedSlow.applyColorFilter(requireContext().getProperTextColor())
playbackSpeedFast.applyColorFilter(requireContext().getProperTextColor())
playbackSpeedSlow.setOnClickListener { reduceSpeed() }
playbackSpeedFast.setOnClickListener { increaseSpeed() }
initSeekbar(playbackSpeedSeekbar, playbackSpeedLabel, config)
}
return view
return binding.root
}
private fun initSeekbar(seekbar: MySeekBar, speedLabel: MyTextView, config: Config) {
@ -87,11 +89,13 @@ class PlaybackSpeedFragment : BottomSheetDialogFragment() {
val lowerProgress = (1 - MIN_PLAYBACK_SPEED) * lowerProgressPercent + MIN_PLAYBACK_SPEED
lowerProgress
}
progress > HALF_PROGRESS -> {
val upperProgressPercent = progress / HALF_PROGRESS.toFloat() - 1
val upperDiff = MAX_PLAYBACK_SPEED - 1
upperDiff * upperProgressPercent + 1
}
else -> 1f
}
playbackSpeed = Math.min(Math.max(playbackSpeed, MIN_PLAYBACK_SPEED), MAX_PLAYBACK_SPEED)

View file

@ -5,35 +5,33 @@ import android.content.Intent
import android.util.AttributeSet
import com.google.gson.Gson
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.activities.TracksActivity
import com.simplemobiletools.musicplayer.adapters.PlaylistsAdapter
import com.simplemobiletools.musicplayer.databinding.FragmentPlaylistsBinding
import com.simplemobiletools.musicplayer.dialogs.ChangeSortingDialog
import com.simplemobiletools.musicplayer.dialogs.NewPlaylistDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.mediaScanner
import com.simplemobiletools.musicplayer.extensions.viewBinding
import com.simplemobiletools.musicplayer.helpers.PLAYLIST
import com.simplemobiletools.musicplayer.helpers.TAB_PLAYLISTS
import com.simplemobiletools.musicplayer.models.Events
import com.simplemobiletools.musicplayer.models.Playlist
import com.simplemobiletools.musicplayer.models.sortSafely
import kotlinx.android.synthetic.main.fragment_playlists.view.playlists_fastscroller
import kotlinx.android.synthetic.main.fragment_playlists.view.playlists_list
import kotlinx.android.synthetic.main.fragment_playlists.view.playlists_placeholder
import kotlinx.android.synthetic.main.fragment_playlists.view.playlists_placeholder_2
import org.greenrobot.eventbus.EventBus
class PlaylistsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
private var playlists = ArrayList<Playlist>()
private val binding by viewBinding(FragmentPlaylistsBinding::bind)
override fun setupFragment(activity: BaseSimpleActivity) {
playlists_placeholder_2.underlineText()
playlists_placeholder_2.setOnClickListener {
binding.playlistsPlaceholder2.underlineText()
binding.playlistsPlaceholder2.setOnClickListener {
NewPlaylistDialog(activity) {
EventBus.getDefault().post(Events.PlaylistsUpdated())
}
@ -50,28 +48,28 @@ class PlaylistsFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
activity.runOnUiThread {
val scanning = activity.mediaScanner.isScanning()
playlists_placeholder.text = if (scanning) {
binding.playlistsPlaceholder.text = if (scanning) {
context.getString(R.string.loading_files)
} else {
context.getString(R.string.no_items_found)
context.getString(com.simplemobiletools.commons.R.string.no_items_found)
}
playlists_placeholder.beVisibleIf(playlists.isEmpty())
playlists_placeholder_2.beVisibleIf(playlists.isEmpty() && !scanning)
binding.playlistsPlaceholder.beVisibleIf(playlists.isEmpty())
binding.playlistsPlaceholder2.beVisibleIf(playlists.isEmpty() && !scanning)
val adapter = playlists_list.adapter
val adapter = binding.playlistsList.adapter
if (adapter == null) {
PlaylistsAdapter(activity, playlists, playlists_list) {
PlaylistsAdapter(activity, playlists, binding.playlistsList) {
activity.hideKeyboard()
Intent(activity, TracksActivity::class.java).apply {
putExtra(PLAYLIST, Gson().toJson(it))
activity.startActivity(this)
}
}.apply {
playlists_list.adapter = this
binding.playlistsList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
playlists_list.scheduleLayoutAnimation()
binding.playlistsList.scheduleLayoutAnimation()
}
} else {
(adapter as PlaylistsAdapter).updateItems(playlists)
@ -81,33 +79,36 @@ class PlaylistsFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
}
override fun finishActMode() {
(playlists_list.adapter as? MyRecyclerViewAdapter)?.finishActMode()
getAdapter()?.finishActMode()
}
override fun onSearchQueryChanged(text: String) {
val filtered = playlists.filter { it.title.contains(text, true) }.toMutableList() as ArrayList<Playlist>
(playlists_list.adapter as? PlaylistsAdapter)?.updateItems(filtered, text)
playlists_placeholder.beVisibleIf(filtered.isEmpty())
playlists_placeholder_2.beVisibleIf(filtered.isEmpty())
getAdapter()?.updateItems(filtered, text)
binding.playlistsPlaceholder.beVisibleIf(filtered.isEmpty())
binding.playlistsPlaceholder2.beVisibleIf(filtered.isEmpty())
}
override fun onSearchClosed() {
(playlists_list.adapter as? PlaylistsAdapter)?.updateItems(playlists)
playlists_placeholder.beGoneIf(playlists.isNotEmpty())
playlists_placeholder_2.beGoneIf(playlists.isNotEmpty())
getAdapter()?.updateItems(playlists)
binding.playlistsPlaceholder.beGoneIf(playlists.isNotEmpty())
binding.playlistsPlaceholder2.beGoneIf(playlists.isNotEmpty())
}
override fun onSortOpen(activity: SimpleActivity) {
ChangeSortingDialog(activity, TAB_PLAYLISTS) {
val adapter = playlists_list.adapter as? PlaylistsAdapter ?: return@ChangeSortingDialog
val adapter = getAdapter() ?: return@ChangeSortingDialog
playlists.sortSafely(activity.config.playlistSorting)
adapter.updateItems(playlists, forceUpdate = true)
}
}
override fun setupColors(textColor: Int, adjustedPrimaryColor: Int) {
playlists_placeholder.setTextColor(textColor)
playlists_placeholder_2.setTextColor(adjustedPrimaryColor)
playlists_fastscroller.updateColors(adjustedPrimaryColor)
binding.playlistsPlaceholder.setTextColor(textColor)
binding.playlistsPlaceholder2.setTextColor(adjustedPrimaryColor)
binding.playlistsFastscroller.updateColors(adjustedPrimaryColor)
getAdapter()?.updateColors(textColor)
}
private fun getAdapter() = binding.playlistsList.adapter as? PlaylistsAdapter
}

View file

@ -4,27 +4,31 @@ import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.extensions.areSystemAnimationsEnabled
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getParentPath
import com.simplemobiletools.commons.extensions.hideKeyboard
import com.simplemobiletools.commons.extensions.openNotificationSettings
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.activities.SimpleActivity
import com.simplemobiletools.musicplayer.adapters.TracksAdapter
import com.simplemobiletools.musicplayer.databinding.FragmentTracksBinding
import com.simplemobiletools.musicplayer.dialogs.ChangeSortingDialog
import com.simplemobiletools.musicplayer.extensions.audioHelper
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.mediaScanner
import com.simplemobiletools.musicplayer.extensions.viewBinding
import com.simplemobiletools.musicplayer.helpers.TAB_TRACKS
import com.simplemobiletools.musicplayer.models.Track
import com.simplemobiletools.musicplayer.models.sortSafely
import kotlinx.android.synthetic.main.fragment_tracks.view.tracks_fastscroller
import kotlinx.android.synthetic.main.fragment_tracks.view.tracks_list
import kotlinx.android.synthetic.main.fragment_tracks.view.tracks_placeholder
// Artists -> Albums -> Tracks
class TracksFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
private var tracks = ArrayList<Track>()
private val binding by viewBinding(FragmentTracksBinding::bind)
override fun setupFragment(activity: BaseSimpleActivity) {
ensureBackgroundThread {
@ -37,15 +41,15 @@ class TracksFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
activity.runOnUiThread {
val scanning = activity.mediaScanner.isScanning()
tracks_placeholder.text = if (scanning) {
binding.tracksPlaceholder.text = if (scanning) {
context.getString(R.string.loading_files)
} else {
context.getString(R.string.no_items_found)
context.getString(com.simplemobiletools.commons.R.string.no_items_found)
}
tracks_placeholder.beVisibleIf(tracks.isEmpty())
val adapter = tracks_list.adapter
binding.tracksPlaceholder.beVisibleIf(tracks.isEmpty())
val adapter = binding.tracksList.adapter
if (adapter == null) {
TracksAdapter(activity = activity, recyclerView = tracks_list, sourceType = TracksAdapter.TYPE_TRACKS, items = tracks) {
TracksAdapter(activity = activity, recyclerView = binding.tracksList, sourceType = TracksAdapter.TYPE_TRACKS, items = tracks) {
activity.hideKeyboard()
activity.handleNotificationPermission { granted ->
if (granted) {
@ -53,16 +57,20 @@ class TracksFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
prepareAndPlay(tracks, startIndex)
} else {
if (context is Activity) {
PermissionRequiredDialog(activity, R.string.allow_notifications_music_player, { activity.openNotificationSettings() })
PermissionRequiredDialog(
activity,
com.simplemobiletools.commons.R.string.allow_notifications_music_player,
{ activity.openNotificationSettings() }
)
}
}
}
}.apply {
tracks_list.adapter = this
binding.tracksList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
tracks_list.scheduleLayoutAnimation()
binding.tracksList.scheduleLayoutAnimation()
}
} else {
(adapter as TracksAdapter).updateItems(tracks)
@ -72,32 +80,35 @@ class TracksFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
}
override fun finishActMode() {
(tracks_list.adapter as? MyRecyclerViewAdapter)?.finishActMode()
getAdapter()?.finishActMode()
}
override fun onSearchQueryChanged(text: String) {
val filtered = tracks.filter {
it.title.contains(text, true) || ("${it.artist} - ${it.album}").contains(text, true)
}.toMutableList() as ArrayList<Track>
(tracks_list.adapter as? TracksAdapter)?.updateItems(filtered, text)
tracks_placeholder.beVisibleIf(filtered.isEmpty())
getAdapter()?.updateItems(filtered, text)
binding.tracksPlaceholder.beVisibleIf(filtered.isEmpty())
}
override fun onSearchClosed() {
(tracks_list.adapter as? TracksAdapter)?.updateItems(tracks)
tracks_placeholder.beGoneIf(tracks.isNotEmpty())
getAdapter()?.updateItems(tracks)
binding.tracksPlaceholder.beGoneIf(tracks.isNotEmpty())
}
override fun onSortOpen(activity: SimpleActivity) {
ChangeSortingDialog(activity, TAB_TRACKS) {
val adapter = tracks_list.adapter as? TracksAdapter ?: return@ChangeSortingDialog
val adapter = getAdapter() ?: return@ChangeSortingDialog
tracks.sortSafely(activity.config.trackSorting)
adapter.updateItems(tracks, forceUpdate = true)
}
}
override fun setupColors(textColor: Int, adjustedPrimaryColor: Int) {
tracks_placeholder.setTextColor(textColor)
tracks_fastscroller.updateColors(adjustedPrimaryColor)
binding.tracksPlaceholder.setTextColor(textColor)
binding.tracksFastscroller.updateColors(adjustedPrimaryColor)
getAdapter()?.updateColors(textColor)
}
private fun getAdapter() = binding.tracksList.adapter as? TracksAdapter
}

View file

@ -4,7 +4,6 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.writeLn
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.models.Track
import java.io.OutputStream
@ -26,7 +25,7 @@ class M3uExporter(val activity: BaseSimpleActivity) {
return
}
activity.toast(R.string.exporting)
activity.toast(com.simplemobiletools.commons.R.string.exporting)
try {
outputStream.bufferedWriter().use { out ->

View file

@ -105,7 +105,7 @@ class MyWidgetProvider : AppWidgetProvider() {
}
private fun updatePlayPauseButton(context: Context, views: RemoteViews, isPlaying: Boolean) {
val drawableId = if (isPlaying) R.drawable.ic_pause_vector else R.drawable.ic_play_vector
val drawableId = if (isPlaying) com.simplemobiletools.commons.R.drawable.ic_pause_vector else com.simplemobiletools.commons.R.drawable.ic_play_vector
val widgetTextColor = context.config.widgetTextColor
val icon = context.resources.getColoredBitmap(drawableId, widgetTextColor)
views.setImageViewBitmap(R.id.play_pause_btn, icon)
@ -120,8 +120,14 @@ class MyWidgetProvider : AppWidgetProvider() {
applyColorFilter(R.id.widget_background, widgetBgColor)
setTextColor(R.id.song_info_title, widgetTextColor)
setTextColor(R.id.song_info_artist, widgetTextColor)
setImageViewBitmap(R.id.previous_btn, context.resources.getColoredBitmap(R.drawable.ic_previous_vector, widgetTextColor))
setImageViewBitmap(R.id.next_btn, context.resources.getColoredBitmap(R.drawable.ic_next_vector, widgetTextColor))
setImageViewBitmap(
R.id.previous_btn,
context.resources.getColoredBitmap(
com.simplemobiletools.commons.R.drawable.ic_previous_vector,
widgetTextColor
)
)
setImageViewBitmap(R.id.next_btn, context.resources.getColoredBitmap(com.simplemobiletools.commons.R.drawable.ic_next_vector, widgetTextColor))
}
}

View file

@ -23,7 +23,7 @@ class NotificationHelper(private val context: Context) {
fun createNoPermissionNotification(): Notification {
return NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(context.getString(R.string.no_storage_permissions))
.setContentTitle(context.getString(com.simplemobiletools.commons.R.string.no_storage_permissions))
.setSmallIcon(R.drawable.ic_headset_small)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_MAX)
@ -34,7 +34,7 @@ class NotificationHelper(private val context: Context) {
}
fun createMediaScannerNotification(contentText: String, progress: Int, max: Int): Notification {
val title = context.getString(R.string.scanning)
val title = context.getString(com.simplemobiletools.commons.R.string.scanning)
return NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(title)
.setSmallIcon(R.drawable.ic_headset_small)
@ -52,7 +52,6 @@ class NotificationHelper(private val context: Context) {
}.build()
}
fun notify(id: Int, notification: Notification) = notificationManager.notify(id, notification)
fun cancel(id: Int) = notificationManager.cancel(id)

View file

@ -71,7 +71,7 @@ class SimpleMediaScanner(private val context: Application) {
} catch (ignored: Exception) {
} finally {
if (showProgress && newTracks.isEmpty()) {
context.toast(R.string.no_items_found)
context.toast(com.simplemobiletools.commons.R.string.no_items_found)
}
newTracks.clear()

View file

@ -21,7 +21,6 @@ data class Folder(val title: String, val trackCount: Int, val path: String) {
}
}
fun getBubbleText(sorting: Int) = when {
sorting and PLAYER_SORT_BY_TITLE != 0 -> title
else -> trackCount.toString()

View file

@ -4,7 +4,6 @@ import android.content.Context
import android.os.Bundle
import androidx.media3.session.CommandButton
import androidx.media3.session.SessionCommand
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.helpers.PATH
/**
@ -32,9 +31,9 @@ internal val customCommands = CustomCommands.values().map { it.sessionCommand }
internal fun Context.getCustomLayout(): List<CommandButton> {
return listOf(
CommandButton.Builder()
.setDisplayName(getString(R.string.close))
.setDisplayName(getString(com.simplemobiletools.commons.R.string.close))
.setSessionCommand(CustomCommands.CLOSE_PLAYER.sessionCommand)
.setIconResId(R.drawable.ic_cross_vector)
.setIconResId(com.simplemobiletools.commons.R.drawable.ic_cross_vector)
.build()
)
}

View file

@ -10,7 +10,6 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.session.*
import com.simplemobiletools.commons.extensions.hasPermission
import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.*
import com.simplemobiletools.musicplayer.helpers.NotificationHelper
import com.simplemobiletools.musicplayer.helpers.getPermissionToRequest
@ -92,7 +91,7 @@ class PlaybackService : MediaLibraryService(), MediaSessionService.Listener {
* background.
*/
override fun onForegroundServiceStartNotAllowedException() {
showErrorToast(getString(R.string.unknown_error_occurred))
showErrorToast(getString(com.simplemobiletools.commons.R.string.unknown_error_occurred))
// todo: show a notification instead.
}

View file

@ -6,7 +6,6 @@ import androidx.media3.common.util.UnstableApi
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.helpers.EQUALIZER_PRESET_CUSTOM
import com.simplemobiletools.musicplayer.playback.player.SimpleMusicPlayer
@ -39,7 +38,7 @@ object SimpleEqualizer {
}
}
} catch (ignored: Exception) {
context.toast(R.string.unknown_error_occurred)
context.toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
}

View file

@ -155,7 +155,11 @@ internal class MediaItemProvider(private val context: Context) {
state = STATE_INITIALIZING
ensureBackgroundThread {
val root = buildMediaItem(title = context.getString(R.string.root), mediaId = SMP_ROOT_ID, mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED)
val root = buildMediaItem(
title = context.getString(com.simplemobiletools.commons.R.string.root),
mediaId = SMP_ROOT_ID,
mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED
)
val rootChildren = RootCategories.buildRootChildren(context)
addNodeAndChildren(item = root, children = rootChildren)
@ -233,7 +237,7 @@ internal class MediaItemProvider(private val context: Context) {
private enum class RootCategories(@StringRes val titleRes: Int, @DrawableRes val drawableRes: Int, val mediaId: String, val mediaType: @MediaType Int) {
PLAYLISTS(R.string.playlists, R.drawable.ic_playlist_vector, SMP_PLAYLISTS_ROOT_ID, MediaMetadata.MEDIA_TYPE_FOLDER_PLAYLISTS),
FOLDERS(R.string.folders, R.drawable.ic_folders_vector, SMP_FOLDERS_ROOT_ID, MediaMetadata.MEDIA_TYPE_FOLDER_PLAYLISTS),
ARTISTS(R.string.artists, R.drawable.ic_person_vector, SMP_ARTISTS_ROOT_ID, MediaMetadata.MEDIA_TYPE_FOLDER_ARTISTS),
ARTISTS(R.string.artists, com.simplemobiletools.commons.R.drawable.ic_person_vector, SMP_ARTISTS_ROOT_ID, MediaMetadata.MEDIA_TYPE_FOLDER_ARTISTS),
ALBUMS(R.string.albums, R.drawable.ic_album_vector, SMP_ALBUMS_ROOT_ID, MediaMetadata.MEDIA_TYPE_FOLDER_ALBUMS),
TRACKS(R.string.tracks, R.drawable.ic_music_note_vector, SMP_TRACKS_ROOT_ID, MediaMetadata.MEDIA_TYPE_PLAYLIST),
GENRES(R.string.genres, R.drawable.ic_genre_vector, SMP_GENRES_ROOT_ID, MediaMetadata.MEDIA_TYPE_FOLDER_GENRES);

View file

@ -6,7 +6,6 @@ import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.config
import com.simplemobiletools.musicplayer.extensions.getPlaybackSetting
import com.simplemobiletools.musicplayer.helpers.PlaybackSetting
@ -15,7 +14,7 @@ import com.simplemobiletools.musicplayer.playback.PlaybackService
@UnstableApi
internal fun PlaybackService.getPlayerListener() = object : Player.Listener {
override fun onPlayerError(error: PlaybackException) = toast(R.string.unknown_error_occurred, Toast.LENGTH_LONG)
override fun onPlayerError(error: PlaybackException) = toast(com.simplemobiletools.commons.R.string.unknown_error_occurred, Toast.LENGTH_LONG)
override fun onEvents(player: Player, events: Player.Events) {
if (
@ -38,15 +37,17 @@ internal fun PlaybackService.getPlayerListener() = object : Player.Listener {
withPlayer {
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT) {
if (config.playbackSetting == PlaybackSetting.STOP_AFTER_CURRENT_TRACK) {
pause()
seekTo(0)
pause()
}
}
}
}
override fun onRepeatModeChanged(repeatMode: Int) {
config.playbackSetting = getPlaybackSetting(repeatMode)
if (config.playbackSetting != PlaybackSetting.STOP_AFTER_CURRENT_TRACK) {
config.playbackSetting = getPlaybackSetting(repeatMode)
}
}
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {

View file

@ -14,24 +14,21 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.musicplayer.R
import com.simplemobiletools.musicplayer.extensions.ensureActivityNotDestroyed
import com.simplemobiletools.musicplayer.extensions.getTrackCoverArt
import com.simplemobiletools.musicplayer.extensions.toTrack
import com.simplemobiletools.musicplayer.extensions.updatePlayPauseIcon
import kotlinx.android.synthetic.main.view_current_track_bar.view.current_track_label
import kotlinx.android.synthetic.main.view_current_track_bar.view.current_track_play_pause
import com.simplemobiletools.musicplayer.databinding.ViewCurrentTrackBarBinding
import com.simplemobiletools.musicplayer.extensions.*
class CurrentTrackBar(context: Context, attributeSet: AttributeSet) : RelativeLayout(context, attributeSet) {
private val binding by viewBinding(ViewCurrentTrackBarBinding::bind)
fun initialize(togglePlayback: () -> Unit) {
current_track_play_pause.setOnClickListener {
binding.currentTrackPlayPause.setOnClickListener {
togglePlayback()
}
}
fun updateColors() {
background = ColorDrawable(context.getProperBackgroundColor())
current_track_label.setTextColor(context.getProperTextColor())
binding.currentTrackLabel.setTextColor(context.getProperTextColor())
}
fun updateCurrentTrack(mediaItem: MediaItem?) {
@ -50,8 +47,8 @@ class CurrentTrackBar(context: Context, attributeSet: AttributeSet) : RelativeLa
}
@SuppressLint("SetTextI18n")
current_track_label.text = "${track.title}$artist"
val cornerRadius = resources.getDimension(R.dimen.rounded_corner_radius_small).toInt()
binding.currentTrackLabel.text = "${track.title}$artist"
val cornerRadius = resources.getDimension(com.simplemobiletools.commons.R.dimen.rounded_corner_radius_small).toInt()
val currentTrackPlaceholder = resources.getColoredDrawableWithColor(R.drawable.ic_headset, context.getProperTextColor())
val options = RequestOptions()
.error(currentTrackPlaceholder)
@ -68,6 +65,6 @@ class CurrentTrackBar(context: Context, attributeSet: AttributeSet) : RelativeLa
}
fun updateTrackState(isPlaying: Boolean) {
current_track_play_pause.updatePlayPauseIcon(isPlaying, context.getProperTextColor())
binding.currentTrackPlayPause.updatePlayPauseIcon(isPlaying, context.getProperTextColor())
}
}

View file

@ -1,37 +0,0 @@
package com.simplemobiletools.musicplayer.views
import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import com.google.android.material.tabs.TabLayout
// make the tabLayout scrollable horizotally when needed, else make sure it fills whole width
class MyTabLayout : TabLayout {
constructor(context: Context?) : super(context!!)
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
try {
if (tabCount == 0) {
return
}
val tabLayout = getChildAt(0) as ViewGroup
val childCount = tabLayout.childCount
val widths = IntArray(childCount + 1)
for (i in 0 until childCount) {
widths[i] = tabLayout.getChildAt(i).measuredWidth
widths[childCount] += widths[i]
}
val measuredWidth = measuredWidth
for (i in 0 until childCount) {
tabLayout.getChildAt(i).minimumWidth = measuredWidth * widths[i] / widths[childCount]
}
} catch (ignored: Exception) {
}
}
}

View file

@ -38,6 +38,7 @@
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
<include
android:id="@+id/current_track_bar"
layout="@layout/view_current_track_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -47,6 +47,7 @@
app:layout_constraintTop_toTopOf="parent" />
<include
android:id="@+id/current_track_bar"
layout="@layout/view_current_track_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -67,6 +67,7 @@
android:visibility="gone" />
<include
android:id="@+id/current_track_bar"
layout="@layout/view_current_track_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -34,5 +34,3 @@
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
</com.simplemobiletools.musicplayer.fragments.GenresFragment>

View file

@ -1,30 +0,0 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

11
build.gradle.kts Normal file
View file

@ -0,0 +1,11 @@
plugins {
alias(libs.plugins.android).apply(false)
alias(libs.plugins.kotlinAndroid).apply(false)
alias(libs.plugins.ksp).apply(false)
}
tasks.register<Delete>("clean") {
delete {
rootProject.buildDir
}
}

View file

@ -1,2 +1,3 @@
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx8192m

69
gradle/libs.versions.toml Normal file
View file

@ -0,0 +1,69 @@
[versions]
#jetbrains
autofittextview = "0.2.1"
desugar_jdk_libs = "2.0.3"
# higher versions of jaudiotagger not compatible with <= API 25 devices
# https://bitbucket.org/ijabz/jaudiotagger/issues/149/some-nio-classes-are-unavailable-while
jaudiotagger = "2.2.5"
kotlin = "1.9.10"
#KSP
ksp = "1.9.10-1.0.13"
#AndroidX
androidx-constraintlayout = "2.1.4"
androidx-swiperefreshlayout = "1.1.0"
androidx-lifecycleprocess = "2.6.1"
#Eventbus
eventbus = "3.3.1"
#Room
lottie = "6.1.0"
m3uParser = "1.3.0"
media = "1.6.0"
media3 = "1.1.1"
room = "2.5.2"
#Simple Mobile Tools
simple-commons = "f64d11af6f"
#Gradle
gradlePlugins-agp = "8.1.0"
#build
app-build-compileSDKVersion = "34"
app-build-targetSDK = "34"
app-build-minimumSDK = "23"
app-build-javaVersion = "VERSION_17"
app-build-kotlinJVMTarget = "17"
#Helpers
shortcut-badger = "1.1.22"
#versioning
app-version-appId = "com.simplemobiletools.musicplayer"
app-version-versionCode = "114"
app-version-versionName = "5.17.1"
[libraries]
#AndroidX
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" }
androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "androidx-lifecycleprocess" }
androidx-media = { module = "androidx.media:media", version.ref = "media" }
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3" }
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "media3" }
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "androidx-swiperefreshlayout" }
#Room
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
#Simple Mobile Tools
simple-mobile-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" }
#EventBus
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" }
#Helpers
desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" }
jaudiotagger = { module = "net.jthink:jaudiotagger", version.ref = "jaudiotagger" }
lottie = { module = "com.airbnb.android:lottie", version.ref = "lottie" }
autofittextview = { module = "me.grantland:autofittextview", version.ref = "autofittextview" }
m3u-parser = { module = "com.github.bjoernpetersen:m3u-parser", version.ref = "m3uParser" }
[bundles]
room = [
"androidx-room-ktx",
"androidx-room-runtime",
]
[plugins]
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

View file

@ -1,6 +1,6 @@
#Mon Nov 02 17:54:10 CET 2020
#Thu Aug 31 16:28:32 IST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip

View file

@ -1 +0,0 @@
include ':app'

16
settings.gradle.kts Normal file
View file

@ -0,0 +1,16 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { setUrl("https://jitpack.io") }
}
}
include(":app")