From 36b61ad5bb89ff8150b02f80212ec10f12f9e733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Mon, 20 Feb 2023 20:38:04 +0100 Subject: [PATCH 1/9] Added the languages page --- .../spowlo/ui/components/PreferenceItems.kt | 2 +- .../bobbyesp/spowlo/ui/pages/InitialEntry.kt | 7 ++ .../settings/appearance/AppearancePage.kt | 4 +- .../pages/settings/appearance/LanguagePage.kt | 106 ++++++++++++++++++ app/src/main/res/values-es/strings.xml | 2 + app/src/main/res/values/strings.xml | 8 +- 6 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/LanguagePage.kt create mode 100644 app/src/main/res/values-es/strings.xml diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/components/PreferenceItems.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/components/PreferenceItems.kt index 6e2e899d..cb1656ec 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/components/PreferenceItems.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/components/PreferenceItems.kt @@ -526,7 +526,7 @@ fun PreferencesHintCard( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 12.dp) - .clip(MaterialTheme.shapes.extraLarge) + .clip(MaterialTheme.shapes.small) .background(backgroundColor) .clickable { onClick() } .padding(horizontal = 12.dp, vertical = 16.dp), diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt index d17acb4a..2fa55fb1 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt @@ -59,6 +59,7 @@ import com.bobbyesp.spowlo.ui.pages.settings.SettingsPage import com.bobbyesp.spowlo.ui.pages.settings.about.AboutPage import com.bobbyesp.spowlo.ui.pages.settings.appearance.AppThemePreferencesPage import com.bobbyesp.spowlo.ui.pages.settings.appearance.AppearancePage +import com.bobbyesp.spowlo.ui.pages.settings.appearance.LanguagePage import com.bobbyesp.spowlo.ui.pages.settings.cookies.CookieProfilePage import com.bobbyesp.spowlo.ui.pages.settings.cookies.CookiesSettingsViewModel import com.bobbyesp.spowlo.ui.pages.settings.cookies.WebViewPage @@ -312,6 +313,12 @@ fun InitialEntry( } } + animatedComposable(Route.LANGUAGES) { + LanguagePage { + onBackPressed() + } + } + navDeepLink { // Want to go to "markdown_viewer/{markdownFileName}" uriPattern = "android-app://androidx.navigation/markdown_viewer/{markdownFileName}" diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/AppearancePage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/AppearancePage.kt index e60d94f0..63871687 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/AppearancePage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/AppearancePage.kt @@ -205,12 +205,12 @@ fun AppearancePage( onClick = { navController.navigate(Route.APP_THEME) } ) //todo: add the languages page - /*if (Build.VERSION.SDK_INT >= 24) + if (Build.VERSION.SDK_INT >= 24) PreferenceItem( title = stringResource(R.string.language), icon = Icons.Outlined.Language, description = getLanguageDesc() - ) { navController.navigate(Route.LANGUAGES) }*/ + ) { navController.navigate(Route.LANGUAGES) } } }) if (showDarkThemeDialog) diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/LanguagePage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/LanguagePage.kt new file mode 100644 index 00000000..9f96a344 --- /dev/null +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/appearance/LanguagePage.kt @@ -0,0 +1,106 @@ +package com.bobbyesp.spowlo.ui.pages.settings.appearance + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Translate +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.bobbyesp.spowlo.MainActivity +import com.bobbyesp.spowlo.R +import com.bobbyesp.spowlo.ui.common.LocalDarkTheme +import com.bobbyesp.spowlo.ui.components.BackButton +import com.bobbyesp.spowlo.ui.components.PreferenceSingleChoiceItem +import com.bobbyesp.spowlo.ui.components.PreferencesHintCard +import com.bobbyesp.spowlo.utils.ChromeCustomTabsUtil +import com.bobbyesp.spowlo.utils.LANGUAGE +import com.bobbyesp.spowlo.utils.PreferencesUtil +import com.bobbyesp.spowlo.utils.PreferencesUtil.getLanguageConfiguration +import com.bobbyesp.spowlo.utils.SYSTEM_DEFAULT +import com.bobbyesp.spowlo.utils.getLanguageDesc +import com.bobbyesp.spowlo.utils.languageMap + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LanguagePage(onBackPressed: () -> Unit) { + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior( + rememberTopAppBarState(), + canScroll = { true } + ) + var language by remember { mutableStateOf(PreferencesUtil.getLanguageNumber()) } + val uriHandler = LocalUriHandler.current + + val spowloWeblateUrl = "https://hosted.weblate.org/engage/spowlo/" + + fun setLanguage(selectedLanguage: Int) { + language = selectedLanguage + PreferencesUtil.encodeInt(LANGUAGE, language) + MainActivity.setLanguage(getLanguageConfiguration()) + } + Scaffold( + modifier = Modifier + .fillMaxSize() + .nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + LargeTopAppBar( + title = { + Text( + modifier = Modifier, + text = stringResource(id = R.string.language), + ) + }, navigationIcon = { + BackButton { + onBackPressed() + } + }, scrollBehavior = scrollBehavior + ) + }, content = { + LazyColumn( + modifier = Modifier + .padding(it) + .selectableGroup() + ) { + item { + PreferencesHintCard( + title = stringResource(R.string.translate), + description = stringResource(R.string.translate_desc), + icon = Icons.Outlined.Translate, + isDarkTheme = LocalDarkTheme.current.isDarkTheme() + ) { ChromeCustomTabsUtil.openUrl(spowloWeblateUrl) } + } + item { + PreferenceSingleChoiceItem( + text = stringResource(R.string.follow_system), + selected = language == SYSTEM_DEFAULT, + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 18.dp) + ) { setLanguage(SYSTEM_DEFAULT) } + } + for (languageData in languageMap) { + item { + PreferenceSingleChoiceItem( + text = getLanguageDesc(languageData.key), + selected = language == languageData.key, + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 18.dp) + ) { setLanguage(languageData.key) } + } + } + } + }) +} \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml new file mode 100644 index 00000000..a6b3daec --- /dev/null +++ b/app/src/main/res/values-es/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4bbd41c3..d86a0d32 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - Spowlo + Spowlo Follow system On Off @@ -9,8 +9,8 @@ %.2f MB %.2f GB This file is no longer available - English (United States) - Español + English (United States) + Español spotDL Documentation Confirm Dismiss @@ -217,4 +217,6 @@ Use caching Use caching for faster previous songs re-downloads SpotDL library settings + Translate the app! + Help translating the app to your language in Hosted Weblate! \ No newline at end of file From 5a02495a960cc58be014742fa6aed6f85d9c0264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Mon, 20 Feb 2023 20:45:33 +0100 Subject: [PATCH 2/9] Moved MD file name getting to a "val" --- .../main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt index 2fa55fb1..fe9d0b55 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt @@ -328,10 +328,10 @@ fun InitialEntry( "markdown_viewer/{markdownFileName}", arguments = listOf(navArgument("markdownFileName") { type = NavType.StringType }) ) { backStackEntry -> - Log.d("MainActivity", backStackEntry.arguments?.getString("markdownFileName") ?: "") + val mdFileName = backStackEntry.arguments?.getString("markdownFileName") ?: "" + Log.d("MainActivity", mdFileName) MarkdownViewerPage( - markdownFileName = backStackEntry.arguments?.getString("markdownFileName") - ?: "", + markdownFileName = mdFileName, onBackPressed = onBackPressed ) } From 64c0c716a7fc4f33171d0beea8de36287565d5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Tue, 21 Feb 2023 10:11:32 +0100 Subject: [PATCH 3/9] Added the link opening in the Markdown Viewer and also added templates for GitHub issues --- .github/ISSUE_TEMPLATE/bug_report.yml | 83 +++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 2 + .github/ISSUE_TEMPLATE/feature_request.yml | 51 ++++++++++++ app/src/main/AndroidManifest.xml | 22 +---- .../spowlo/ui/pages/MarkdownViewerPage.kt | 23 +++++ 5 files changed, 160 insertions(+), 21 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..e7e8198e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,83 @@ +name: Bug Report +description: Create a report to help us improve +labels: [bug] +body: + + + - type: checkboxes + id: checklist + attributes: + label: Checklist + description: | + Carefully read and work through this check list in order to prevent the most common mistakes and misuse of Spowlo/spotDL (note that most of the bugs are caused by the spotDL library and we need to report them in their repo): + options: + - label: I've verified that I'm running the latest [**stable version**](https://github.com/JunkFood02/Seal/releases/latest/) of Seal or any later [**preview versions**](https://github.com/JunkFood02/Seal/releases). + required: true + - label: I've checked that the YouTube Music is available in my country. + required: true + - label: I understand that the issue will be (ignored/closed) if I intentionally remove or skip any mandatory field. + required: true + + - type: textarea + attributes: + label: Describe the bug + description: + placeholder: | + A clear and concise description of what the bug is. + validations: + required: false + + - type: textarea + attributes: + label: To Reproduce + placeholder: | + Steps to reproduce the behavior: + 1.Go to '...' + 2.Click on '....' + 3.Scroll down to '....' + 4.See error + validations: + required: false + + - type: textarea + attributes: + label: Error reports + placeholder: | + Click on the displayed error below the text box area to copy it. + validations: + required: true + + - type: textarea + attributes: + label: Screenshots & Screen Records + placeholder: | + Screenshots & Screen Records can amp up bug reports. + validations: + required: false + + - type: textarea + attributes: + label: Device info + description: | + Please provide some information of the device you are using. + You can get the device info by doing these steps: + 1) Open Spowlo + 2) Go to settings + 3) Click on About + 4) Scroll all the way down + 5) Click "Version" + 6) Paste the info below. + placeholder: | + App version: x.x.x (XxXxX) + Device information: Android XX (API XX) + Supported ABIs: [arm64-v8a, armeabi-v7a, armeabi] + spotDL version: X.X.X + validations: + required: false + + - type: textarea + attributes: + label: Additional context + description: + placeholder: | + Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..0db72d2a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,2 @@ +# disable blank issue creation +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..02e889aa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,51 @@ +name: Feature Request +description: Suggest a new feature for the general download mode +title: "[Feature Request]" +labels: [enhancement] +body: + - type: checkboxes + id: checklist + attributes: + label: Checklist + description: | + Even if you're not sure about the answer, feel free to leave it blank and provide us with more information about this request. + options: + - label: This feature I'm requesting is already implemented in spotDL. + required: false + - label: This feature is intended to be a UI/UX update. + required: false + - label: This feature is not going to conflict with many of the existing options. + required: false + - type: textarea + id: description_1 + attributes: + label: Is your feature request related to a problem? Please describe it and link to the GitHub issue. + description: + placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + validations: + required: false + - type: textarea + id: description_2 + attributes: + label: Describe the solution you'd like + description: + placeholder: A clear and concise description of what you want to include in the app. + validations: + required: false + - type: textarea + id: description_3 + attributes: + label: Song/playlist link + description: + placeholder: Please provide us with a link to the video for which this feature might be beneficial. + validations: + required: false + - type: textarea + id: description_4 + attributes: + label: Additional context + description: + placeholder: Add any other context or screenshots about the feature request here. + validations: + required: false + render: shell diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 69ff12f1..85f808cb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -37,6 +37,7 @@ android:localeConfig="@xml/locales_config" android:requestLegacyExternalStorage="true" android:supportsRtl="true" + android:largeHeap="true" tools:targetApi="tiramisu"> - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/MarkdownViewerPage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/MarkdownViewerPage.kt index ca1aca8e..833557f0 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/MarkdownViewerPage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/MarkdownViewerPage.kt @@ -19,10 +19,29 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import coil.ImageLoader +import coil.disk.DiskCache +import coil.memory.MemoryCache +import com.bobbyesp.spowlo.App import com.bobbyesp.spowlo.R import com.bobbyesp.spowlo.ui.components.BackButton +import com.bobbyesp.spowlo.utils.ChromeCustomTabsUtil import dev.jeziellago.compose.markdowntext.MarkdownText +val imageLoader = ImageLoader.Builder(App.context) + .memoryCache { + MemoryCache.Builder(App.context) + .maxSizePercent(0.25) + .build() + } + .diskCache { + DiskCache.Builder() + .directory(App.context.cacheDir.resolve("image_cache")) + .maxSizePercent(0.02) + .build() + } + .build() + @OptIn(ExperimentalMaterial3Api::class) @Composable fun MarkdownViewerPage( @@ -63,6 +82,10 @@ fun MarkdownViewerPage( markdown = markdownText, textAlign = TextAlign.Justify, color = if (isSystemInDarkTheme()) Color.White else Color.Black, + onLinkClicked = { url -> + ChromeCustomTabsUtil.openUrl(url) + }, + imageLoader = imageLoader ) } } From 1c8af10c96e87752b5208168a347248e04d51953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Tue, 21 Feb 2023 18:21:56 +0100 Subject: [PATCH 4/9] Added languages and created a hole new update dialog --- app/build.gradle.kts | 4 +- app/src/main/AndroidManifest.xml | 2 +- app/src/main/java/com/bobbyesp/spowlo/App.kt | 11 - .../spowlo/ui/components/PreferenceItems.kt | 2 +- .../ui/dialogs/DownloaderSettingsDialog.kt | 7 +- .../spowlo/ui/dialogs/UpdaterBottomDrawer.kt | 193 ++++++++++++++++++ .../bobbyesp/spowlo/ui/pages/InitialEntry.kt | 63 +++--- .../directories/DownloadsDirectoriesPage.kt | 5 - .../settings/format/SettingsFormatsPage.kt | 8 +- .../spotify/SpotifySettingsDialogs.kt | 21 +- .../bobbyesp/spowlo/utils/LanguageSettings.kt | 100 ++++++++- .../com/bobbyesp/spowlo/utils/UpdateUtil.kt | 30 +++ app/src/main/res/values/strings.xml | 45 +++- 13 files changed, 423 insertions(+), 68 deletions(-) create mode 100644 app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/UpdaterBottomDrawer.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 23ad3113..3c7d7c47 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -42,8 +42,8 @@ sealed class Version( } val currentVersion: Version = Version.Stable( - versionMajor = 1, - versionMinor = 0, + versionMajor = 0, + versionMinor = 2, versionPatch = 0, ) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 85f808cb..3737b598 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -37,8 +37,8 @@ android:localeConfig="@xml/locales_config" android:requestLegacyExternalStorage="true" android:supportsRtl="true" - android:largeHeap="true" tools:targetApi="tiramisu"> + + currentDownloadStatus = downloadStatus + if (downloadStatus is UpdateUtil.DownloadStatus.Finished) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + UpdateUtil.installLatestApk() + } + } + } + }.onFailure { + it.printStackTrace() + currentDownloadStatus = UpdateUtil.DownloadStatus.NotYet + ToastUtil.makeToastSuspend(context.getString(R.string.app_update_failed)) + return@launch + } + } + }, + onDismiss = { + hideDrawer(scope) + } + ) +} + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun UpdaterBottomDrawerImpl( + drawerState: ModalBottomSheetState, + version: String, + changelog: String, + downloadUrl: String, + downloadStatus: UpdateUtil.DownloadStatus, + onConfirmUpdate: () -> Unit = {}, + onDismiss: () -> Unit = {}, +) { + BottomDrawer(drawerState = drawerState, sheetContent = { + Column(modifier = Modifier.fillMaxWidth()) { + Text( + text = version, + style = MaterialTheme.typography.headlineMedium, + color = if (isSystemInDarkTheme()) Color.White else Color.Black + ) + Text( + text = stringResource(id = R.string.update_available), + style = MaterialTheme.typography.labelMedium, + color = if (isSystemInDarkTheme()) Color.White else Color.Black, + modifier = Modifier.alpha(0.6f) + ) + HorizontalDivider(modifier = Modifier.padding(vertical = 6.dp, horizontal = 8.dp)) + LazyColumn( + Modifier + .fillMaxWidth() + .size(300.dp)) { + item { + MarkdownText( + modifier = Modifier + .fillMaxWidth() + .padding(6.dp), + markdown = changelog, + textAlign = TextAlign.Justify, + color = if (isSystemInDarkTheme()) Color.White else Color.Black, + onLinkClicked = { url -> + ChromeCustomTabsUtil.openUrl(url) + }, + imageLoader = imageLoader + ) + } + } + HorizontalDivider(modifier = Modifier.padding(vertical = 6.dp, horizontal = 8.dp)) + AnimatedVisibility(visible = downloadStatus is UpdateUtil.DownloadStatus.Progress) { + LinearProgressIndicator( + modifier = Modifier + .fillMaxWidth() + .padding(6.dp), progress = when (downloadStatus) { + is UpdateUtil.DownloadStatus.Progress -> downloadStatus.percent.toFloat() / 100f + else -> 0f + } + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .horizontalScroll(rememberScrollState()) + .padding(top = 8.dp), + ) { + OutlinedButtonWithIcon( + modifier = Modifier + .padding(horizontal = 12.dp) + .weight(1f), + onClick = onDismiss, + icon = Icons.Outlined.Cancel, + text = stringResource(R.string.cancel) + ) + FilledTonalButtonWithIcon( + modifier = Modifier + .padding(horizontal = 12.dp) + .weight(1f), + onClick = onConfirmUpdate, + icon = Icons.Outlined.Download, + text = stringResource(R.string.update) + ) + + } + } + }) +} + +@OptIn(ExperimentalMaterialApi::class) +fun hideDrawer(scope: CoroutineScope) { + if (UpdateUtil.updateViewState.value.drawerState.isVisible) { + scope.launch { + UpdateUtil.updateViewState.value.drawerState.hide() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt index fe9d0b55..9e85fdef 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/InitialEntry.kt @@ -49,6 +49,7 @@ import com.bobbyesp.spowlo.ui.common.Route import com.bobbyesp.spowlo.ui.common.animatedComposable import com.bobbyesp.spowlo.ui.common.slideInVerticallyComposable import com.bobbyesp.spowlo.ui.dialogs.UpdateDialogImpl +import com.bobbyesp.spowlo.ui.dialogs.UpdaterBottomDrawer import com.bobbyesp.spowlo.ui.pages.downloader.DownloaderPage import com.bobbyesp.spowlo.ui.pages.downloader.DownloaderViewModel import com.bobbyesp.spowlo.ui.pages.history.DownloadsHistoryPage @@ -347,6 +348,9 @@ fun InitialEntry( latestRelease = it showUpdateDialog = true } + if(showUpdateDialog){ + UpdateUtil.showUpdateDrawer() + } }.onFailure { it.printStackTrace() } @@ -354,35 +358,36 @@ fun InitialEntry( } if (showUpdateDialog) { - UpdateDialogImpl( - onDismissRequest = { - showUpdateDialog = false - updateJob?.cancel() - }, - title = latestRelease.name.toString(), - onConfirmUpdate = { - updateJob = scope.launch(Dispatchers.IO) { - runCatching { - UpdateUtil.downloadApk(latestRelease = latestRelease) - .collect { downloadStatus -> - currentDownloadStatus = downloadStatus - if (downloadStatus is UpdateUtil.DownloadStatus.Finished) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - launcher.launch(Manifest.permission.REQUEST_INSTALL_PACKAGES) - } - } - } - }.onFailure { - it.printStackTrace() - currentDownloadStatus = UpdateUtil.DownloadStatus.NotYet - ToastUtil.makeToastSuspend(context.getString(R.string.app_update_failed)) - return@launch - } - } - }, - releaseNote = latestRelease.body.toString(), - downloadStatus = currentDownloadStatus - ) + /*UpdateDialogImpl( + onDismissRequest = { + showUpdateDialog = false + updateJob?.cancel() + }, + title = latestRelease.name.toString(), + onConfirmUpdate = { + updateJob = scope.launch(Dispatchers.IO) { + runCatching { + UpdateUtil.downloadApk(latestRelease = latestRelease) + .collect { downloadStatus -> + currentDownloadStatus = downloadStatus + if (downloadStatus is UpdateUtil.DownloadStatus.Finished) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + launcher.launch(Manifest.permission.REQUEST_INSTALL_PACKAGES) + } + } + } + }.onFailure { + it.printStackTrace() + currentDownloadStatus = UpdateUtil.DownloadStatus.NotYet + ToastUtil.makeToastSuspend(context.getString(R.string.app_update_failed)) + return@launch + } + } + }, + releaseNote = latestRelease.body.toString(), + downloadStatus = currentDownloadStatus + )*/ + UpdaterBottomDrawer(latestRelease = latestRelease) } } diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/directories/DownloadsDirectoriesPage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/directories/DownloadsDirectoriesPage.kt index 9905826a..f8e5aed0 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/directories/DownloadsDirectoriesPage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/directories/DownloadsDirectoriesPage.kt @@ -176,11 +176,6 @@ fun DownloadsDirectoriesPage( ) }, content = { LazyColumn(modifier = Modifier.padding(it)) { - - if (isCustomCommandEnabled) - item { - PreferenceInfo(text = stringResource(id = R.string.custom_command_enabled_hint)) - } if(sdcardUri.isEmpty()) item { PreferenceInfo(text = stringResource(id = R.string.sdcard_not_activable_hint)) diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt index 1e1eb4a6..d9d21ab0 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt @@ -71,10 +71,6 @@ fun SettingsFormatsPage(onBackPressed: () -> Unit) { ) } LazyColumn(Modifier.padding(it)) { - if (isCustomCommandEnabled) - item { - PreferenceInfo(text = stringResource(id = R.string.custom_command_enabled_hint)) - } item { PreferenceSubtitle(text = stringResource(id = R.string.audio)) } @@ -95,7 +91,7 @@ fun SettingsFormatsPage(onBackPressed: () -> Unit) { title = stringResource(R.string.audio_format), description = audioFormat, icon = Icons.Outlined.AudioFile, - enabled = true, //!isCustomCommandEnabled // !preserveOriginalAudio + enabled = true, ) { showAudioFormatDialog = true } } item { @@ -103,7 +99,7 @@ fun SettingsFormatsPage(onBackPressed: () -> Unit) { title = stringResource(R.string.audio_quality), description = audioQuality, icon = Icons.Outlined.HighQuality, - enabled = !preserveOriginalAudio, //!isCustomCommandEnabled || + enabled = !preserveOriginalAudio, ) { showAudioQualityDialog = true } } } diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/spotify/SpotifySettingsDialogs.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/spotify/SpotifySettingsDialogs.kt index bc7c4d28..c3119e82 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/spotify/SpotifySettingsDialogs.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/spotify/SpotifySettingsDialogs.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.DeveloperMode import androidx.compose.material.icons.outlined.Key import androidx.compose.material.icons.outlined.Language import androidx.compose.material.icons.outlined.PermIdentity @@ -29,6 +30,8 @@ import com.bobbyesp.spowlo.ui.common.stringState import com.bobbyesp.spowlo.ui.components.ConfirmButton import com.bobbyesp.spowlo.ui.components.DismissButton import com.bobbyesp.spowlo.ui.components.LinkButton +import com.bobbyesp.spowlo.ui.components.OutlinedButtonChip +import com.bobbyesp.spowlo.utils.ChromeCustomTabsUtil import com.bobbyesp.spowlo.utils.PreferencesUtil import com.bobbyesp.spowlo.utils.PreferencesUtil.updateString import com.bobbyesp.spowlo.utils.SPOTIFY_CLIENT_ID @@ -57,7 +60,14 @@ fun SpotifyClientIDDialog(onDismissRequest: () -> Unit) { }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done) ) - LinkButton(link = spotifyDeveloperConsoleUrl, text = stringResource(id = R.string.spotify_developer_console)) + OutlinedButtonChip( + onClick = { + ChromeCustomTabsUtil.openUrl( + spotifyDeveloperConsoleUrl + ) + }, label = stringResource(id = R.string.spotify_developer_console), + icon = Icons.Outlined.DeveloperMode + ) } }, confirmButton = { ConfirmButton() { @@ -92,7 +102,14 @@ fun SpotifyClientSecretDialog(onDismissRequest: () -> Unit) { }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done) ) - LinkButton(link = spotifyDeveloperConsoleUrl, text = stringResource(id = R.string.spotify_developer_console)) + OutlinedButtonChip( + onClick = { + ChromeCustomTabsUtil.openUrl( + spotifyDeveloperConsoleUrl + ) + }, label = stringResource(id = R.string.spotify_developer_console), + icon = Icons.Outlined.DeveloperMode + ) } }, confirmButton = { ConfirmButton() { diff --git a/app/src/main/java/com/bobbyesp/spowlo/utils/LanguageSettings.kt b/app/src/main/java/com/bobbyesp/spowlo/utils/LanguageSettings.kt index a185b8e4..d9bcdf77 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/utils/LanguageSettings.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/utils/LanguageSettings.kt @@ -23,19 +23,115 @@ fun getLanguageNumber(): Int { fun getLanguageDesc(language: Int = getLanguageNumber()): String { return stringResource( when (language) { + SIMPLIFIED_CHINESE -> R.string.la_zh_CN ENGLISH -> R.string.la_en_US + CZECH -> R.string.la_cs + FRENCH -> R.string.la_fr + GERMAN -> R.string.la_de + NORWEGIAN_BOKMAL -> R.string.la_nb + DANISH -> R.string.la_da SPANISH -> R.string.la_es + TURKISH -> R.string.la_tr + UKRAINIAN -> R.string.la_uk + RUSSIAN -> R.string.la_ru + ARABIC -> R.string.la_ar + PERSIAN -> R.string.la_fa + INDONESIAN -> R.string.la_in + FILIPINO -> R.string.la_fil + ITALIAN -> R.string.la_it + DUTCH -> R.string.la_nl + PORTUGUESE_BRAZIL -> R.string.la_pt_BR + JAPANESE -> R.string.la_ja + POLISH -> R.string.la_pl + HUNGARIAN -> R.string.la_hu + MALAY -> R.string.la_ms + TRADITIONAL_CHINESE -> R.string.la_zh_TW + VIETNAMESE -> R.string.la_vi + BELARUSIAN -> R.string.la_be + CROATIAN -> R.string.la_hr + BASQUE -> R.string.la_eu + HINDI -> R.string.la_hi + MALAYALAM -> R.string.la_ml + SINHALA -> R.string.la_si + SERBIAN -> R.string.la_sr + AZERBAIJANI -> R.string.la_az + NORWEGIAN_NYNORSK -> R.string.la_nn + PUNJABI -> R.string.la_pa else -> R.string.follow_system } ) } // Do not modify -private const val ENGLISH = 1 -private const val SPANISH = 2 +private const val SIMPLIFIED_CHINESE = 1 +private const val ENGLISH = 2 +private const val CZECH = 3 +private const val FRENCH = 4 +private const val GERMAN = 5 +private const val NORWEGIAN_BOKMAL = 6 +private const val DANISH = 7 +private const val SPANISH = 8 +private const val TURKISH = 9 +private const val UKRAINIAN = 10 +private const val RUSSIAN = 11 +private const val ARABIC = 12 +private const val PERSIAN = 13 +private const val INDONESIAN = 14 +private const val FILIPINO = 15 +private const val ITALIAN = 16 +private const val DUTCH = 17 +private const val PORTUGUESE_BRAZIL = 18 +private const val JAPANESE = 19 +private const val POLISH = 20 +private const val HUNGARIAN = 21 +private const val MALAY = 22 +private const val TRADITIONAL_CHINESE = 23 +private const val VIETNAMESE = 24 +private const val BELARUSIAN = 25 +private const val CROATIAN = 26 +private const val BASQUE = 27 +private const val HINDI = 28 +private const val MALAYALAM = 29 +private const val SINHALA = 30 +private const val SERBIAN = 31 +private const val AZERBAIJANI = 32 +private const val NORWEGIAN_NYNORSK = 33 +private const val PUNJABI = 34 // Sorted alphabetically val languageMap: Map = mapOf( + ARABIC to "ar", + AZERBAIJANI to "az", + BASQUE to "eu", + BELARUSIAN to "be", + SIMPLIFIED_CHINESE to "zh-CN", + TRADITIONAL_CHINESE to "zh-TW", + CROATIAN to "hr", + CZECH to "cs", + DANISH to "da", + DUTCH to "nl", ENGLISH to "en-US", + FILIPINO to "fil", + FRENCH to "fr", + GERMAN to "de", + HINDI to "hi", + HUNGARIAN to "hu", + INDONESIAN to "in", + ITALIAN to "it", + JAPANESE to "ja", + MALAY to "ms", + MALAYALAM to "ml", + NORWEGIAN_BOKMAL to "nb", + NORWEGIAN_NYNORSK to "nn", + PERSIAN to "fa", + POLISH to "pl", + PORTUGUESE_BRAZIL to "pt-BR", + PUNJABI to "pa", + RUSSIAN to "ru", + SERBIAN to "sr", + SINHALA to "si", SPANISH to "es", + TURKISH to "tr", + UKRAINIAN to "uk", + VIETNAMESE to "vi", ) \ No newline at end of file diff --git a/app/src/main/java/com/bobbyesp/spowlo/utils/UpdateUtil.kt b/app/src/main/java/com/bobbyesp/spowlo/utils/UpdateUtil.kt index 1bb7beb3..0c96be92 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/utils/UpdateUtil.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/utils/UpdateUtil.kt @@ -5,16 +5,23 @@ import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.util.Log +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ModalBottomSheetState +import androidx.compose.material.ModalBottomSheetValue import androidx.core.content.FileProvider import com.bobbyesp.spowlo.App import com.bobbyesp.spowlo.R +import com.bobbyesp.spowlo.ui.pages.history.DownloadsHistoryViewModel import com.bobbyesp.spowlo.utils.PreferencesUtil.getInt import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.update import kotlinx.coroutines.withContext import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -33,8 +40,31 @@ import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine +@OptIn(ExperimentalMaterialApi::class) object UpdateUtil { + data class UpdateViewState( + val drawerState: ModalBottomSheetState = ModalBottomSheetState( + ModalBottomSheetValue.Hidden, isSkipHalfExpanded = true + ), + ) + + private val _updateViewState = MutableStateFlow(UpdateViewState()) + val updateViewState = _updateViewState.asStateFlow() + + fun showUpdateDrawer(){ + _updateViewState.update { + it.copy(drawerState = ModalBottomSheetState(ModalBottomSheetValue.Expanded)) + } + } + + fun hideUpdateDrawer(){ + _updateViewState.update { + it.copy(drawerState = ModalBottomSheetState(ModalBottomSheetValue.Hidden)) + } + } + + private const val OWNER = "BobbyESP" private const val REPO = "Spowlo" private const val ARM64 = "arm64-v8a" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d86a0d32..25d8fc14 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,8 +9,6 @@ %.2f MB %.2f GB This file is no longer available - English (United States) - Español spotDL Documentation Confirm Dismiss @@ -25,27 +23,22 @@ Open settings Edit Remove template - Some options are unavailable when using custom commands Lyrics An error happened while trying to update the app. Update Permission denied - Custom command template An unknown error occurred. The error output has been copied to the clipboard. A download is currently in progress. Completed Download Downloads history - Custom tasks running Settings Spotify URL or query Activate the usage of the app in background to make sure that all works fine. Battery configuration General Appearance - Custom commands - Use custom commands to get the most out of the library. Change how the app looks like About Telegram, GitHub, bug reports… @@ -219,4 +212,42 @@ SpotDL library settings Translate the app! Help translating the app to your language in Hosted Weblate! + + Bokmål + Čeština + Deutsch + 简体中文 + English + Français + Dansk + Español + Türkçe + Русский + عربي + Українська + Indonesia + فارسی + Filipino + Italiano + Nederlands + Português Brasileiro + 日本語 + Polski + Magyar + беларуская + Melayu + 繁體中文 + Tiếng Việt + Hrvatski + Euskara + हिन्दी + മലയാളം + සිංහල + Српски + Azərbaycanca + Nynorsk + ਪੰਜਾਬੀ + A new update is available! + + \ No newline at end of file From 49a7d6df9bbfe0aeb07fe23ecefc92bd3325e55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Tue, 21 Feb 2023 18:57:02 +0100 Subject: [PATCH 5/9] Added a copy link button to the update drawer --- .../spowlo/ui/dialogs/UpdaterBottomDrawer.kt | 60 ++++++++++++++----- .../history/DownloadHistoryBottomDrawer.kt | 27 ++++++--- .../bobbyesp/spowlo/ui/theme/ColorScheme.kt | 7 ++- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/UpdaterBottomDrawer.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/UpdaterBottomDrawer.kt index 18b460d8..9f371e7f 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/UpdaterBottomDrawer.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/UpdaterBottomDrawer.kt @@ -11,20 +11,26 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.rememberScrollState import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.IconButton import androidx.compose.material.ModalBottomSheetState import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Cancel +import androidx.compose.material.icons.outlined.ContentCopy import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Download +import androidx.compose.material.icons.outlined.Link +import androidx.compose.material3.Icon import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -34,21 +40,27 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.bobbyesp.spowlo.App.Companion.context import com.bobbyesp.spowlo.R +import com.bobbyesp.spowlo.ui.common.LocalWindowWidthState import com.bobbyesp.spowlo.ui.components.BottomDrawer import com.bobbyesp.spowlo.ui.components.FilledTonalButtonWithIcon import com.bobbyesp.spowlo.ui.components.HorizontalDivider import com.bobbyesp.spowlo.ui.components.OutlinedButtonWithIcon import com.bobbyesp.spowlo.ui.pages.imageLoader +import com.bobbyesp.spowlo.ui.theme.contraryColor import com.bobbyesp.spowlo.utils.ChromeCustomTabsUtil +import com.bobbyesp.spowlo.utils.GeneralTextUtils import com.bobbyesp.spowlo.utils.ToastUtil import com.bobbyesp.spowlo.utils.UpdateUtil import dev.jeziellago.compose.markdowntext.MarkdownText @@ -111,24 +123,43 @@ fun UpdaterBottomDrawerImpl( onConfirmUpdate: () -> Unit = {}, onDismiss: () -> Unit = {}, ) { + val clipboardManager = LocalClipboardManager.current + + BottomDrawer(drawerState = drawerState, sheetContent = { Column(modifier = Modifier.fillMaxWidth()) { - Text( - text = version, - style = MaterialTheme.typography.headlineMedium, - color = if (isSystemInDarkTheme()) Color.White else Color.Black - ) - Text( - text = stringResource(id = R.string.update_available), - style = MaterialTheme.typography.labelMedium, - color = if (isSystemInDarkTheme()) Color.White else Color.Black, - modifier = Modifier.alpha(0.6f) - ) + Row(modifier = Modifier.fillMaxWidth()) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = version, + style = MaterialTheme.typography.headlineMedium, + color = contraryColor() + ) + Text( + text = stringResource(id = R.string.update_available), + style = MaterialTheme.typography.labelMedium, + color = contraryColor(), + modifier = Modifier.alpha(0.6f) + ) + } + IconButton(onClick = { + clipboardManager.setText(AnnotatedString(downloadUrl)) + ToastUtil.makeToast(context.getString(R.string.link_copied)) + }) { + Icon( + imageVector = Icons.Outlined.Link, + contentDescription = null, + tint = MaterialTheme.colorScheme.surfaceTint + ) + } + } HorizontalDivider(modifier = Modifier.padding(vertical = 6.dp, horizontal = 8.dp)) LazyColumn( Modifier .fillMaxWidth() - .size(300.dp)) { + .size(300.dp) + + ) { item { MarkdownText( modifier = Modifier @@ -136,7 +167,7 @@ fun UpdaterBottomDrawerImpl( .padding(6.dp), markdown = changelog, textAlign = TextAlign.Justify, - color = if (isSystemInDarkTheme()) Color.White else Color.Black, + color = contraryColor(), onLinkClicked = { url -> ChromeCustomTabsUtil.openUrl(url) }, @@ -159,7 +190,8 @@ fun UpdaterBottomDrawerImpl( modifier = Modifier .fillMaxWidth() .horizontalScroll(rememberScrollState()) - .padding(top = 8.dp), + .padding(top = 8.dp) + .navigationBarsPadding(), ) { OutlinedButtonWithIcon( modifier = Modifier diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/history/DownloadHistoryBottomDrawer.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/history/DownloadHistoryBottomDrawer.kt index 5fd3e481..31dd18bf 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/history/DownloadHistoryBottomDrawer.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/history/DownloadHistoryBottomDrawer.kt @@ -88,7 +88,7 @@ fun DownloadHistoryBottomDrawer(downloadsHistoryViewModel: DownloadsHistoryViewM downloadsHistoryViewModel.hideDrawer(scope) } - LaunchedEffect(viewState.drawerState.targetValue){ + LaunchedEffect(viewState.drawerState.targetValue) { delay(100) showDeleteDialog = false deleteFile = false @@ -138,11 +138,11 @@ fun DownloadHistoryBottomDrawerImpl( songUrl: String, artworkUrl: String, onShowDeleteDialog: () -> Unit, - onDeleteCallback : () -> Unit, + onDeleteCallback: () -> Unit, onOpenLink: () -> Unit, onShareFile: () -> Unit, deleteFile: Boolean = false, - onClickDeleteFile : () -> Unit, + onClickDeleteFile: () -> Unit, showDeleteInfo: Boolean = false ) { val clipboardManager = LocalClipboardManager.current @@ -251,12 +251,21 @@ fun DownloadHistoryBottomDrawerImpl( tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(32.dp) ) - Column(modifier = Modifier - .fillMaxWidth() - .padding(start = 6.dp)) { - Text(text = stringResource(R.string.remove_song), fontWeight = FontWeight.Bold) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(start = 6.dp) + ) { + Text( + text = stringResource(R.string.remove_song), + fontWeight = FontWeight.Bold + ) Spacer(modifier = Modifier.height(3.dp)) - Text(text = stringResource(R.string.are_you_sure), modifier = Modifier.alpha(alpha = 0.75f), fontSize = 12.sp) + Text( + text = stringResource(R.string.are_you_sure), + modifier = Modifier.alpha(alpha = 0.75f), + fontSize = 12.sp + ) } } Text( @@ -280,7 +289,7 @@ fun DownloadHistoryBottomDrawerImpl( .padding(horizontal = 12.dp) .weight(1f), onClick = { - onShowDeleteDialog() + onShowDeleteDialog() }, icon = Icons.Outlined.Cancel, text = stringResource(R.string.cancel) diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/theme/ColorScheme.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/theme/ColorScheme.kt index c8c761e2..e44ca672 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/theme/ColorScheme.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/theme/ColorScheme.kt @@ -1,6 +1,7 @@ package com.bobbyesp.spowlo.ui.theme import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape @@ -38,5 +39,9 @@ fun BlurEffect( content() } } +const val DEFAULT_SEED_COLOR = 0xFF415f76.toInt() -const val DEFAULT_SEED_COLOR = 0xFF415f76.toInt() \ No newline at end of file +@Composable +fun contraryColor(): Color { + return if (isSystemInDarkTheme()) Color.White else Color.Black +} \ No newline at end of file From 65d00801ca3778f2f477ec3ef93a7e3c516cd2b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Wed, 22 Feb 2023 12:04:57 +0100 Subject: [PATCH 6/9] Added errors showing below the text box --- .../ui/dialogs/DownloaderSettingsDialog.kt | 21 +++++++++++ .../downloader/FullscreenConsoleOutput.kt | 2 ++ .../settings/cookies/CookiesSettingsPage.kt | 2 ++ .../settings/general/GeneralSettingsPage.kt | 22 ++++++++++-- .../bobbyesp/spowlo/utils/DownloaderUtil.kt | 36 +++++++++++++++---- .../bobbyesp/spowlo/utils/PreferencesUtil.kt | 4 ++- app/src/main/res/values/strings.xml | 2 ++ 7 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/bobbyesp/spowlo/ui/pages/downloader/FullscreenConsoleOutput.kt diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/DownloaderSettingsDialog.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/DownloaderSettingsDialog.kt index ad9cfa37..8d7e591e 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/DownloaderSettingsDialog.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/dialogs/DownloaderSettingsDialog.kt @@ -65,6 +65,7 @@ import com.bobbyesp.spowlo.ui.pages.settings.spotify.SpotifyClientIDDialog import com.bobbyesp.spowlo.ui.pages.settings.spotify.SpotifyClientSecretDialog import com.bobbyesp.spowlo.utils.COOKIES import com.bobbyesp.spowlo.utils.CUSTOM_COMMAND +import com.bobbyesp.spowlo.utils.DONT_FILTER_RESULTS import com.bobbyesp.spowlo.utils.ORIGINAL_AUDIO import com.bobbyesp.spowlo.utils.PreferencesUtil import com.bobbyesp.spowlo.utils.PreferencesUtil.templateStateFlow @@ -131,6 +132,14 @@ fun DownloaderSettingsDialog( ) } + var dontFilter by remember { + mutableStateOf( + settings.getValue( + DONT_FILTER_RESULTS + ) + ) + } + var useSyncedLyrics by remember { mutableStateOf( settings.getValue(SYNCED_LYRICS) @@ -307,6 +316,18 @@ fun DownloaderSettingsDialog( } } ) + + AudioFilterChip( + label = stringResource(id = R.string.dont_filter_results), + selected = dontFilter, + animated = true, + onClick = { + dontFilter = !dontFilter + scope.launch { + settings.updateValue(DONT_FILTER_RESULTS, dontFilter) + } + } + ) AudioFilterChip( label = stringResource(id = R.string.use_cookies), animated = true, diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/downloader/FullscreenConsoleOutput.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/downloader/FullscreenConsoleOutput.kt new file mode 100644 index 00000000..d71ca0bf --- /dev/null +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/downloader/FullscreenConsoleOutput.kt @@ -0,0 +1,2 @@ +package com.bobbyesp.spowlo.ui.pages.downloader + diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/cookies/CookiesSettingsPage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/cookies/CookiesSettingsPage.kt index 706127ed..8e1532c5 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/cookies/CookiesSettingsPage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/cookies/CookiesSettingsPage.kt @@ -63,6 +63,7 @@ import com.bobbyesp.spowlo.ui.components.BackButton import com.bobbyesp.spowlo.ui.components.ConfirmButton import com.bobbyesp.spowlo.ui.components.DismissButton import com.bobbyesp.spowlo.ui.components.HelpDialog +import com.bobbyesp.spowlo.ui.components.HorizontalDivider import com.bobbyesp.spowlo.ui.components.PasteFromClipBoardButton import com.bobbyesp.spowlo.ui.components.PreferenceItemVariant import com.bobbyesp.spowlo.ui.components.PreferenceSwitchWithContainer @@ -158,6 +159,7 @@ fun CookieProfilePage( } item { + HorizontalDivider() PreferenceItemVariant( title = stringResource(id = R.string.generate_new_cookies), icon = Icons.Outlined.Add diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/general/GeneralSettingsPage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/general/GeneralSettingsPage.kt index 574b6512..74345b3e 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/general/GeneralSettingsPage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/general/GeneralSettingsPage.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Cached +import androidx.compose.material.icons.outlined.Filter import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Print import androidx.compose.material.icons.outlined.PrintDisabled @@ -40,6 +41,7 @@ import com.bobbyesp.spowlo.ui.components.PreferenceSubtitle import com.bobbyesp.spowlo.ui.components.PreferenceSwitch import com.bobbyesp.spowlo.utils.CUSTOM_COMMAND import com.bobbyesp.spowlo.utils.DEBUG +import com.bobbyesp.spowlo.utils.DONT_FILTER_RESULTS import com.bobbyesp.spowlo.utils.PreferencesUtil import com.bobbyesp.spowlo.utils.USE_CACHING import kotlinx.coroutines.DelicateCoroutinesApi @@ -69,9 +71,9 @@ fun GeneralSettingsPage( ) } - val isCustomCommandEnabled by remember { + var dontFilter by remember { mutableStateOf( - PreferencesUtil.getValue(CUSTOM_COMMAND) + PreferencesUtil.getValue(DONT_FILTER_RESULTS) ) } @@ -130,7 +132,7 @@ fun GeneralSettingsPage( title = stringResource(R.string.print_details), description = stringResource(R.string.print_details_desc), icon = if (displayErrorReport) Icons.Outlined.Print else Icons.Outlined.PrintDisabled, - enabled = !isCustomCommandEnabled, + enabled = true, onClick = { displayErrorReport = !displayErrorReport PreferencesUtil.updateValue(DEBUG, displayErrorReport) @@ -156,6 +158,20 @@ fun GeneralSettingsPage( isChecked = useCache ) } + item { + PreferenceSwitch( + title = stringResource(id = R.string.dont_filter_results), + description = stringResource(id = R.string.dont_filter_results_desc), + icon = Icons.Outlined.Filter, + onClick = { + scope.launch { + dontFilter = !dontFilter + PreferencesUtil.updateValue(DONT_FILTER_RESULTS, dontFilter) + } + }, + isChecked = dontFilter + ) + } } }) } \ No newline at end of file diff --git a/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt b/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt index bf45873f..f4d922f7 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt @@ -6,6 +6,7 @@ import android.webkit.CookieManager import androidx.annotation.CheckResult import com.bobbyesp.library.SpotDL import com.bobbyesp.library.SpotDLRequest +import com.bobbyesp.library.SpotDLResponse import com.bobbyesp.library.dto.Song import com.bobbyesp.spowlo.App.Companion.audioDownloadDir import com.bobbyesp.spowlo.App.Companion.context @@ -58,6 +59,7 @@ object DownloaderUtil { val useCookies: Boolean = PreferencesUtil.getValue(COOKIES), val useSyncedLyrics: Boolean = PreferencesUtil.getValue(SYNCED_LYRICS), val useCaching: Boolean = PreferencesUtil.getValue(USE_CACHING), + val dontFilter: Boolean = PreferencesUtil.getValue(DONT_FILTER_RESULTS), val formatId: String = "", val privateMode: Boolean = PreferencesUtil.getValue(PRIVATE_MODE), val sdcard: Boolean = PreferencesUtil.getValue(SDCARD_DOWNLOAD), @@ -225,23 +227,27 @@ object DownloaderUtil { pathBuilder.append(audioDownloadDir) Log.d(TAG, "downloadSong: $pathBuilder") - if(useCookies){ + if (useCookies) { useCookies() } - if(!useCaching){ + if (!useCaching) { addOption("--no-cache") } - if(useYtMetadata){ + if (useYtMetadata) { addOption("--ytm-data") } - if(useSyncedLyrics){ + if (dontFilter) { + addOption("--dont-filter-results") + } + + if (useSyncedLyrics) { addOption("--lyrics", "synced") } - if(preserveOriginalAudio) { + if (preserveOriginalAudio) { addOption("--bitrate", "disable") addAudioFormat() } else { @@ -249,11 +255,13 @@ object DownloaderUtil { addAudioFormat() } - if(useSpotifyPreferences){ + if (useSpotifyPreferences) { addOption("--client-id", spotifyClientID) addOption("--client-secret", spotifyClientSecret) } + addOption("--audio", "youtube") + for (s in request.buildCommand()) Log.d(TAG, s) }.runCatching { SpotDL.getInstance().execute(this, taskId, callback = progressCallback) @@ -266,7 +274,21 @@ object DownloaderUtil { downloadPath = pathBuilder.toString(), sdcardUri = sdcardUri ) - } else Result.failure(th) + } else { + return Result.failure(th) + } + }.onSuccess { response -> + return when{ + response.output.contains("LookupError") -> Result.failure(Throwable("A LookupError occurred. The song wasn't found.")) + response.output.contains("YT-DLP") -> Result.failure(Throwable("An error occurred to yt-dlp while downloading the song. Please, report this issue in GitHub.")) + else -> onFinishDownloading( + this, + songInfo = songInfo, + downloadPath = pathBuilder.toString(), + sdcardUri = sdcardUri + ) + + } } return onFinishDownloading( this, diff --git a/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt b/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt index 4e126f8b..e4827fb2 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt @@ -55,6 +55,7 @@ const val SPOTIFY_CLIENT_ID = "spotify_client_id" const val SPOTIFY_CLIENT_SECRET = "spotify_client_secret" const val USE_CACHING = "use_caching" +const val DONT_FILTER_RESULTS = "dont_filter_results" const val TEMPLATE_ID = "template_id" const val MAX_FILE_SIZE = "max_file_size" @@ -73,7 +74,7 @@ const val SYSTEM_DEFAULT = 0 const val STABLE = 0 const val PRE_RELEASE = 1 -const val TEMPLATE_EXAMPLE = """--audio youtube-music --dont-filter-results --preserve-original-audio""" +const val TEMPLATE_EXAMPLE = """--audio youtube-music --dont-filter-results""" private val StringPreferenceDefaults = mapOf( @@ -93,6 +94,7 @@ private val BooleanPreferenceDefaults = SYNCED_LYRICS to false, AUTO_UPDATE to true, USE_CACHING to true, + DONT_FILTER_RESULTS to false, ) private val IntPreferenceDefaults = mapOf( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 25d8fc14..89c92ff3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -248,6 +248,8 @@ Nynorsk ਪੰਜਾਬੀ A new update is available! + Don\'t filter results + If your download wasn\'t succesful or the song not found, using this command should work all. \ No newline at end of file From cb4b27a775f45c86742933fcbdc52c89c76f0f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Wed, 22 Feb 2023 12:05:38 +0100 Subject: [PATCH 7/9] Deleted YT as principal music audio provider --- app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt b/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt index f4d922f7..2d9a6cff 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt @@ -260,8 +260,6 @@ object DownloaderUtil { addOption("--client-secret", spotifyClientSecret) } - addOption("--audio", "youtube") - for (s in request.buildCommand()) Log.d(TAG, s) }.runCatching { SpotDL.getInstance().execute(this, taskId, callback = progressCallback) From 3c2ceb79669f5bc42d27899b31efc03171c2facf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Thu, 23 Feb 2023 16:18:54 +0100 Subject: [PATCH 8/9] Added the ability to choose the audio provider and bumped up yt-dlp --- app/build.gradle.kts | 4 +- .../spowlo/ui/components/DialogItems.kt | 31 ++++++++ .../settings/format/AudioProviderDialog.kt | 76 +++++++++++++++++++ .../settings/format/FormatSettingsDialogs.kt | 18 +++-- .../settings/format/SettingsFormatsPage.kt | 15 ++++ .../bobbyesp/spowlo/utils/DownloaderUtil.kt | 2 + .../bobbyesp/spowlo/utils/PreferencesUtil.kt | 24 ++++++ app/src/main/res/drawable/icons8_youtube.xml | 6 ++ .../res/drawable/youtube_music_icons8.xml | 9 +++ app/src/main/res/values/strings.xml | 7 +- gradle/libs.versions.toml | 2 +- 11 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/AudioProviderDialog.kt create mode 100644 app/src/main/res/drawable/icons8_youtube.xml create mode 100644 app/src/main/res/drawable/youtube_music_icons8.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3c7d7c47..0d3082d2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -42,8 +42,8 @@ sealed class Version( } val currentVersion: Version = Version.Stable( - versionMajor = 0, - versionMinor = 2, + versionMajor = 1, + versionMinor = 1, versionPatch = 0, ) diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/components/DialogItems.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/components/DialogItems.kt index 6928e294..88bcbd9d 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/components/DialogItems.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/components/DialogItems.kt @@ -5,9 +5,11 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Checkbox +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.Text @@ -16,6 +18,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.unit.dp @@ -46,6 +49,34 @@ fun SingleChoiceItem( } } +@Composable +fun SingleChoiceItemWithIcon( + modifier: Modifier = Modifier, text: String, selected: Boolean, onClick: () -> Unit, icon: ImageVector +) { + Row( + modifier = modifier + .padding(vertical = 2.dp) + .clip(CircleShape) + .selectable( + selected = selected, + enabled = true, + onClick = onClick, + ) + .fillMaxWidth() +// .padding(vertical = 12.dp) + , verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start + ) { + RadioButton( + modifier = Modifier.clearAndSetSemantics { }, selected = selected, onClick = onClick + ) + Icon(imageVector = icon, null, modifier = Modifier.padding(horizontal = 8.dp).size(32.dp)) + Text( +// modifier = Modifier.padding(start = 18.dp), + text = text, style = MaterialTheme.typography.bodyLarge + ) + } +} + @Composable fun MultiChoiceItem( modifier: Modifier = Modifier, diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/AudioProviderDialog.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/AudioProviderDialog.kt new file mode 100644 index 00000000..86e5ef2d --- /dev/null +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/AudioProviderDialog.kt @@ -0,0 +1,76 @@ +package com.bobbyesp.spowlo.ui.pages.settings.format + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.MusicNote +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.bobbyesp.spowlo.R +import com.bobbyesp.spowlo.ui.components.ConfirmButton +import com.bobbyesp.spowlo.ui.components.SingleChoiceItemWithIcon +import com.bobbyesp.spowlo.utils.AUDIO_PROVIDER +import com.bobbyesp.spowlo.utils.PreferencesUtil + +@Composable +fun AudioProviderDialog( + onDismissRequest: () -> Unit +) { + var audioProvider by remember { mutableStateOf(PreferencesUtil.getAudioProvider()) } + AlertDialog( + onDismissRequest = onDismissRequest, + title = { Text(stringResource(id = R.string.audio_provider)) }, + icon = { Icon(Icons.Outlined.MusicNote, null) }, + text = { + Column() { + Text( + stringResource(id = R.string.audio_provider_desc), + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + .padding(horizontal = 24.dp), + style = MaterialTheme.typography.bodyLarge + ) + LazyColumn { + for (i in 0..1) { + item { + SingleChoiceItemWithIcon( + text = PreferencesUtil.getAudioProviderDesc(i), + selected = audioProvider == i, + icon = PreferencesUtil.getAudioProviderIcon(i), + onClick = { + audioProvider = i + } + ) + } + } + } + } + }, + confirmButton = { + ConfirmButton( + onClick = { + PreferencesUtil.encodeInt(AUDIO_PROVIDER, audioProvider) + onDismissRequest() + } + ) + }, + dismissButton = { TextButton(onClick = { onDismissRequest() }) { + Text(text = stringResource(id = R.string.dismiss)) + } }, + ) + +} \ No newline at end of file diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/FormatSettingsDialogs.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/FormatSettingsDialogs.kt index 224eb8b4..3efe396f 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/FormatSettingsDialogs.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/FormatSettingsDialogs.kt @@ -3,6 +3,8 @@ package com.bobbyesp.spowlo.ui.pages.settings.format import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons @@ -88,7 +90,7 @@ fun AudioQualityDialog(onDismissRequest: () -> Unit, onConfirm: () -> Unit = {}) Text(text = stringResource(R.string.confirm)) } }, text = { - Column(modifier = Modifier.verticalScroll(rememberScrollState())) { + Column(modifier = Modifier) { Text( modifier = Modifier .fillMaxWidth() @@ -96,11 +98,15 @@ fun AudioQualityDialog(onDismissRequest: () -> Unit, onConfirm: () -> Unit = {}) text = stringResource(R.string.audio_quality_desc), style = MaterialTheme.typography.bodyLarge ) - for (i in 0..17) - SingleChoiceItem( - text = PreferencesUtil.getAudioQualityDesc(i), - selected = audioQuality == i - ) { audioQuality = i } + LazyColumn(content = { + for (i in 0..17) + item { + SingleChoiceItem( + text = PreferencesUtil.getAudioQualityDesc(i), + selected = audioQuality == i + ) { audioQuality = i } + } + }, modifier = Modifier.size(400.dp)) } }) } diff --git a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt index d9d21ab0..d3dc8844 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/ui/pages/settings/format/SettingsFormatsPage.kt @@ -45,6 +45,7 @@ fun SettingsFormatsPage(onBackPressed: () -> Unit) { var showAudioFormatDialog by remember { mutableStateOf(false) } var showAudioQualityDialog by remember { mutableStateOf(false) } + var showAudioProviderDialog by remember { mutableStateOf(false) } Scaffold( @@ -102,6 +103,14 @@ fun SettingsFormatsPage(onBackPressed: () -> Unit) { enabled = !preserveOriginalAudio, ) { showAudioQualityDialog = true } } + item { + PreferenceItem( + title = stringResource(R.string.audio_provider), + description = stringResource(R.string.audio_provider_desc), + icon = Icons.Outlined.HighQuality, + enabled = !isCustomCommandEnabled, + ) { showAudioProviderDialog = true } + } } }) if (showAudioFormatDialog) { @@ -118,4 +127,10 @@ fun SettingsFormatsPage(onBackPressed: () -> Unit) { audioQuality = PreferencesUtil.getAudioQualityDesc() } } + if (showAudioProviderDialog) { + AudioProviderDialog( + onDismissRequest = { showAudioProviderDialog = false } + ) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt b/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt index 2d9a6cff..c002b003 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/utils/DownloaderUtil.kt @@ -255,6 +255,8 @@ object DownloaderUtil { addAudioFormat() } + addOption("--audio", PreferencesUtil.getAudioProviderDesc()) + if (useSpotifyPreferences) { addOption("--client-id", spotifyClientID) addOption("--client-secret", spotifyClientSecret) diff --git a/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt b/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt index e4827fb2..32eb9bd8 100644 --- a/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt +++ b/app/src/main/java/com/bobbyesp/spowlo/utils/PreferencesUtil.kt @@ -3,6 +3,7 @@ package com.bobbyesp.spowlo.utils import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.core.os.LocaleListCompat import com.bobbyesp.spowlo.App @@ -11,6 +12,7 @@ import com.bobbyesp.spowlo.App.Companion.isFDroidBuild import com.bobbyesp.spowlo.R import com.bobbyesp.spowlo.database.CommandTemplate import com.bobbyesp.spowlo.database.CookieProfile +import com.bobbyesp.spowlo.ui.pages.settings.about.LocalAsset import com.bobbyesp.spowlo.ui.theme.DEFAULT_SEED_COLOR import com.google.android.material.color.DynamicColors import com.kyant.monet.PaletteStyle @@ -57,6 +59,8 @@ const val SPOTIFY_CLIENT_SECRET = "spotify_client_secret" const val USE_CACHING = "use_caching" const val DONT_FILTER_RESULTS = "dont_filter_results" +const val AUDIO_PROVIDER = "audio_provider" + const val TEMPLATE_ID = "template_id" const val MAX_FILE_SIZE = "max_file_size" const val COOKIES = "cookies" @@ -105,6 +109,7 @@ private val IntPreferenceDefaults = mapOf( WELCOME_DIALOG to 1, AUDIO_FORMAT to 5, AUDIO_QUALITY to 17, + AUDIO_PROVIDER to 0, UPDATE_CHANNEL to STABLE, ) @@ -141,6 +146,8 @@ object PreferencesUtil { fun getAudioFormat(): Int = AUDIO_FORMAT.getInt() + fun getAudioProvider(): Int = AUDIO_PROVIDER.getInt() + fun getAudioQuality(): Int = AUDIO_QUALITY.getInt() fun getAudioFormatDesc(audioQualityStr: Int = getAudioFormat()): String { @@ -155,6 +162,23 @@ object PreferencesUtil { } } + fun getAudioProviderDesc(audioProviderInt: Int = getAudioProvider()): String { + return when (audioProviderInt){ + 0 -> "youtube-music" + 1 -> "youtube" + else -> "youtube-music" + } + } + + @Composable + fun getAudioProviderIcon(audioProviderInt: Int = getAudioProvider()): ImageVector { + return when (audioProviderInt){ + 0 -> LocalAsset(id = R.drawable.youtube_music_icons8) + 1 -> LocalAsset(id = R.drawable.icons8_youtube) + else -> LocalAsset(id = R.drawable.youtube_music_icons8) + } + } + fun getAudioQualityDesc(audioQualityStr: Int = getAudioQuality()): String { return when (audioQualityStr) { 0 -> "8k" diff --git a/app/src/main/res/drawable/icons8_youtube.xml b/app/src/main/res/drawable/icons8_youtube.xml new file mode 100644 index 00000000..830dcec9 --- /dev/null +++ b/app/src/main/res/drawable/icons8_youtube.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/drawable/youtube_music_icons8.xml b/app/src/main/res/drawable/youtube_music_icons8.xml new file mode 100644 index 00000000..0033eb43 --- /dev/null +++ b/app/src/main/res/drawable/youtube_music_icons8.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 89c92ff3..a5e42bd8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -247,9 +247,10 @@ Azərbaycanca Nynorsk ਪੰਜਾਬੀ + A new update is available! Don\'t filter results - If your download wasn\'t succesful or the song not found, using this command should work all. - - + Do not filter searching results in the available platforms. + Audio provider + Choose from where you want to download the songs \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 232cab45..98733490 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ androidxHiltNavigationCompose = "1.0.0" androidxTestExt = "1.1.4" -spotdlAndroidVersion = "4.1.0-preview-SNAPSHOT" +spotdlAndroidVersion = "884fabd1ba" spotifyApiKotlinVersion = "3.8.8" crashHandlerVersion = "2.0.2" From adce184cf060f8b4c6ffb411adc7cf3c7baa2527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Font=C3=A1n?= Date: Thu, 23 Feb 2023 16:19:21 +0100 Subject: [PATCH 9/9] Added database scheme --- .../1.json | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 app/schemas/com.bobbyesp.spowlo.database.AppDatabase/1.json diff --git a/app/schemas/com.bobbyesp.spowlo.database.AppDatabase/1.json b/app/schemas/com.bobbyesp.spowlo.database.AppDatabase/1.json new file mode 100644 index 00000000..1db99d4e --- /dev/null +++ b/app/schemas/com.bobbyesp.spowlo.database.AppDatabase/1.json @@ -0,0 +1,168 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "78f4ae7565b93534b8ac54a8016a98d3", + "entities": [ + { + "tableName": "CommandShortcut", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `option` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "option", + "columnName": "option", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CommandTemplate", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `template` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "template", + "columnName": "template", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CookieProfile", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "DownloadedSongInfo", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `songName` TEXT NOT NULL, `songAuthor` TEXT NOT NULL, `songUrl` TEXT NOT NULL, `thumbnailUrl` TEXT NOT NULL, `songPath` TEXT NOT NULL, `songDuration` REAL NOT NULL DEFAULT 0.0, `extractor` TEXT NOT NULL DEFAULT 'Unknown')", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "songName", + "columnName": "songName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "songAuthor", + "columnName": "songAuthor", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "songUrl", + "columnName": "songUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "thumbnailUrl", + "columnName": "thumbnailUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "songPath", + "columnName": "songPath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "songDuration", + "columnName": "songDuration", + "affinity": "REAL", + "notNull": true, + "defaultValue": "0.0" + }, + { + "fieldPath": "extractor", + "columnName": "extractor", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'Unknown'" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '78f4ae7565b93534b8ac54a8016a98d3')" + ] + } +} \ No newline at end of file