From 40d26eadcc9cacb2c195dd305f3b7a19ab2377b5 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 30 Jun 2024 17:08:44 +0200 Subject: [PATCH] feat: support for only playing music from certain directories --- .../domain/repository/LocalMusicRepository.kt | 21 +++- .../screens/settings/SettingsScreen.kt | 17 +++ .../components/LocalMusicPathsDialog.kt | 108 ++++++++++++++++++ .../java/app/suhasdissa/vibeyou/utils/Pref.kt | 2 + app/src/main/res/values/strings.xml | 4 + 5 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/components/LocalMusicPathsDialog.kt diff --git a/app/src/main/java/app/suhasdissa/vibeyou/domain/repository/LocalMusicRepository.kt b/app/src/main/java/app/suhasdissa/vibeyou/domain/repository/LocalMusicRepository.kt index 3740f53..29863b9 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/domain/repository/LocalMusicRepository.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/domain/repository/LocalMusicRepository.kt @@ -51,19 +51,34 @@ class LocalMusicRepository( MediaStore.Audio.Media.ARTIST_ID, MediaStore.Audio.Media.DATE_MODIFIED, MediaStore.Audio.Media.DATE_ADDED, - MediaStore.Audio.Media.CD_TRACK_NUMBER + MediaStore.Audio.Media.CD_TRACK_NUMBER, + MediaStore.Audio.Media.RELATIVE_PATH ) val sortOrder = "${MediaStore.Audio.Media.TITLE} ASC" + val showAllMusic = Pref.sharedPreferences.getBoolean(Pref.showAllMusicKey, true) + val musicDirectories = Pref.sharedPreferences.getStringSet(Pref.musicDirectoriesKey, setOf()).orEmpty() + + var sqlQueryString = "" + if (!showAllMusic) { + for (index in musicDirectories.indices) { + sqlQueryString += "${MediaStore.Audio.Media.RELATIVE_PATH} LIKE ?" + if (index != musicDirectories.size - 1) sqlQueryString += " OR " + } + } + val query = contentResolver.query( collection, projection, - null, - null, + sqlQueryString, + if (!showAllMusic) musicDirectories.map { + path -> "${path}%" + }.toTypedArray() else null, sortOrder ) query?.use { cursor -> + val pathColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.RELATIVE_PATH) val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID) val titleColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE) diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt index 1560f3c..39b97f5 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt @@ -40,6 +40,7 @@ import app.suhasdissa.vibeyou.backend.models.Login import app.suhasdissa.vibeyou.backend.viewmodel.AuthViewModel import app.suhasdissa.vibeyou.navigation.Destination import app.suhasdissa.vibeyou.presentation.screens.settings.components.CacheSizeDialog +import app.suhasdissa.vibeyou.presentation.screens.settings.components.LocalMusicPathsDialog import app.suhasdissa.vibeyou.presentation.screens.settings.components.SettingItem @OptIn(ExperimentalMaterial3Api::class) @@ -53,6 +54,7 @@ fun SettingsScreen( val authViewModel: AuthViewModel = viewModel(factory = AuthViewModel.Factory) val topBarBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() var showImageCacheDialog by remember { mutableStateOf(false) } + var showSelectMusicPathsDialog by remember { mutableStateOf(false) } val view = LocalView.current Scaffold(modifier = modifier.fillMaxSize(), topBar = { @@ -115,6 +117,16 @@ fun SettingsScreen( icon = Icons.Rounded.Storage ) } + item { + SettingItem( + title = stringResource(R.string.local_music_paths), + description = stringResource(R.string.local_music_paths_description), + onClick = { + showSelectMusicPathsDialog = true + }, + icon = Icons.Rounded.Landscape + ) + } /* item { SettingItem( @@ -169,4 +181,9 @@ fun SettingsScreen( showImageCacheDialog = false } } + if (showSelectMusicPathsDialog) { + LocalMusicPathsDialog { + showSelectMusicPathsDialog = false + } + } } diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/components/LocalMusicPathsDialog.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/components/LocalMusicPathsDialog.kt new file mode 100644 index 0000000..e7392d2 --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/components/LocalMusicPathsDialog.kt @@ -0,0 +1,108 @@ +package app.suhasdissa.vibeyou.presentation.screens.settings.components + +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.RemoveCircleOutline +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.toMutableStateList +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.core.content.edit +import androidx.documentfile.provider.DocumentFile +import app.suhasdissa.vibeyou.R +import app.suhasdissa.vibeyou.utils.Pref +import app.suhasdissa.vibeyou.utils.rememberPreference + +@Composable +fun LocalMusicPathsDialog(onDismissRequest: () -> Unit) { + val context = LocalContext.current + + var allAvailableMusic by rememberPreference(key = Pref.showAllMusicKey, defaultValue = true) + val musicPaths = remember { + Pref.sharedPreferences.getStringSet(Pref.musicDirectoriesKey, setOf()).orEmpty().toMutableStateList() + } + + val chooseFolderLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.OpenDocumentTree()) { uri -> + val file = DocumentFile.fromTreeUri(context, uri ?: return@rememberLauncherForActivityResult) ?: return@rememberLauncherForActivityResult + val relativePath = file.uri.path?.split(":")?.last().toString() + musicPaths.add(relativePath) + Pref.sharedPreferences.edit { + putStringSet(Pref.musicDirectoriesKey, musicPaths.toSet()) + } + } + + AlertDialog( + onDismissRequest = onDismissRequest, + title = { + Text(text = stringResource(id = R.string.local_music_paths)) + }, + text = { + Column( + modifier = Modifier.fillMaxWidth() + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + modifier = Modifier.weight(1f), + text = stringResource(id = R.string.all_available_music) + ) + Switch(checked = allAvailableMusic, onCheckedChange = { + allAvailableMusic = it + }) + } + + AnimatedVisibility(visible = !allAvailableMusic) { + LazyColumn { + items(musicPaths.toList()) { path -> + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + modifier = Modifier.weight(1f), + text = path + ) + IconButton( + onClick = { + musicPaths.remove(path) + Pref.sharedPreferences.edit { + putStringSet(Pref.musicDirectoriesKey, musicPaths.toSet()) + } + } + ) { + Icon(Icons.Default.RemoveCircleOutline, contentDescription = null) + } + } + } + + item { + Button(onClick = { chooseFolderLauncher.launch(null) }) { + Text(text = stringResource(id = R.string.add_folder)) + } + } + } + } + } + }, + confirmButton = { + TextButton(onClick = onDismissRequest) { + Text(text = stringResource(id = R.string.ok)) + } + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/utils/Pref.kt b/app/src/main/java/app/suhasdissa/vibeyou/utils/Pref.kt index 025513a..0fc399d 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/utils/Pref.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/utils/Pref.kt @@ -23,6 +23,8 @@ object Pref { const val equalizerKey = "equalizer" const val equalizerPresetKey = "equalizerPreset" const val equalizerBandsKey = "equalizerBands" + const val showAllMusicKey = "showAllMusicKey" + const val musicDirectoriesKey = "musicDirectoriesKey" lateinit var sharedPreferences: SharedPreferences diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 521ab69..cbaf824 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -98,4 +98,8 @@ Enabled None Reset equalizer + Local music paths + Select where to load local music from. + Add folder + All available music