From b1781c654f453f4c4511407379b9182c796f0f30 Mon Sep 17 00:00:00 2001 From: junkfood <69683722+JunkFood02@users.noreply.github.com> Date: Thu, 7 Mar 2024 19:27:43 +0800 Subject: [PATCH] feat(ui): configure initial selected download type --- .../ui/common/motion/MaterialSharedAxis.kt | 33 +-- .../com/junkfood/seal/ui/component/Buttons.kt | 10 +- .../junkfood/seal/ui/component/DialogItems.kt | 15 +- .../com/junkfood/seal/ui/component/Dialogs.kt | 6 +- .../seal/ui/component/PreferenceItems.kt | 17 +- .../page/download/DownloadSettingsDialog.kt | 257 +++++++++++------- .../appearance/AppearancePreferences.kt | 36 ++- .../InterfaceCustomizationDialogs.kt | 60 ++++ .../directory/DownloadDirectoryPreferences.kt | 6 +- .../settings/format/FormatSettingDialogs.kt | 24 +- .../settings/network/CookieProfilesPage.kt | 4 +- .../com/junkfood/seal/util/PreferenceUtil.kt | 12 +- app/src/main/res/values/strings.xml | 6 +- 13 files changed, 315 insertions(+), 171 deletions(-) create mode 100644 app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/InterfaceCustomizationDialogs.kt diff --git a/app/src/main/java/com/junkfood/seal/ui/common/motion/MaterialSharedAxis.kt b/app/src/main/java/com/junkfood/seal/ui/common/motion/MaterialSharedAxis.kt index d676c073e4..b3c96bb517 100644 --- a/app/src/main/java/com/junkfood/seal/ui/common/motion/MaterialSharedAxis.kt +++ b/app/src/main/java/com/junkfood/seal/ui/common/motion/MaterialSharedAxis.kt @@ -121,43 +121,32 @@ public fun materialSharedAxisXOut( /** * [materialSharedAxisY] allows to switch a layout with shared Y-axis transition. * - * @param forward whether the direction of the animation is forward. - * @param slideDistance the slide distance of transition. - * @param durationMillis the duration of transition. */ public fun materialSharedAxisY( - forward: Boolean, - slideDistance: Int, + initialOffsetX: (fullWidth: Int) -> Int, + targetOffsetY: (fullWidth: Int) -> Int, durationMillis: Int = MotionConstants.DefaultMotionDuration, ): ContentTransform = materialSharedAxisYIn( - forward = forward, - slideDistance = slideDistance, + initialOffsetX = initialOffsetX, durationMillis = durationMillis ) togetherWith materialSharedAxisYOut( - forward = forward, - slideDistance = slideDistance, + targetOffsetY = targetOffsetY, durationMillis = durationMillis ) /** * [materialSharedAxisYIn] allows to switch a layout with shared Y-axis enter transition. * - * @param forward whether the direction of the animation is forward. - * @param slideDistance the slide distance of the enter transition. - * @param durationMillis the duration of the enter transition. */ public fun materialSharedAxisYIn( - forward: Boolean, - slideDistance: Int, + initialOffsetX: (fullWidth: Int) -> Int, durationMillis: Int = MotionConstants.DefaultMotionDuration, ): EnterTransition = slideInVertically( animationSpec = tween( durationMillis = durationMillis, easing = FastOutSlowInEasing ), - initialOffsetY = { - if (forward) slideDistance else -slideDistance - } + initialOffsetY = initialOffsetX ) + fadeIn( animationSpec = tween( durationMillis = durationMillis.ForIncoming, @@ -169,22 +158,16 @@ public fun materialSharedAxisYIn( /** * [materialSharedAxisYOut] allows to switch a layout with shared Y-axis exit transition. * - * @param forward whether the direction of the animation is forward. - * @param slideDistance the slide distance of the exit transition. - * @param durationMillis the duration of the exit transition. */ public fun materialSharedAxisYOut( - forward: Boolean, - slideDistance: Int, + targetOffsetY: (fullWidth: Int) -> Int, durationMillis: Int = MotionConstants.DefaultMotionDuration, ): ExitTransition = slideOutVertically( animationSpec = tween( durationMillis = durationMillis, easing = FastOutSlowInEasing ), - targetOffsetY = { - if (forward) -slideDistance else slideDistance - } + targetOffsetY = targetOffsetY ) + fadeOut( animationSpec = tween( durationMillis = durationMillis.ForOutgoing, diff --git a/app/src/main/java/com/junkfood/seal/ui/component/Buttons.kt b/app/src/main/java/com/junkfood/seal/ui/component/Buttons.kt index 77b0ab2df3..085c3ac3ce 100644 --- a/app/src/main/java/com/junkfood/seal/ui/component/Buttons.kt +++ b/app/src/main/java/com/junkfood/seal/ui/component/Buttons.kt @@ -72,7 +72,7 @@ fun TextButtonWithIcon( text: String, contentColor: Color = MaterialTheme.colorScheme.primary, onClick: () -> Unit, - ) { +) { TextButton( modifier = modifier, onClick = onClick, @@ -123,14 +123,16 @@ fun FilledTonalButtonWithIcon( @Composable fun FilledButtonWithIcon( modifier: Modifier = Modifier, - onClick: () -> Unit, icon: ImageVector, - text: String + text: String, + enabled: Boolean = true, + onClick: () -> Unit, ) { Button( modifier = modifier, onClick = onClick, - contentPadding = ButtonDefaults.ButtonWithIconContentPadding + contentPadding = ButtonDefaults.ButtonWithIconContentPadding, + enabled = enabled ) { Icon( diff --git a/app/src/main/java/com/junkfood/seal/ui/component/DialogItems.kt b/app/src/main/java/com/junkfood/seal/ui/component/DialogItems.kt index fd90fe598c..e75c9a67ea 100644 --- a/app/src/main/java/com/junkfood/seal/ui/component/DialogItems.kt +++ b/app/src/main/java/com/junkfood/seal/ui/component/DialogItems.kt @@ -35,7 +35,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @Composable -fun SingleChoiceItem( +fun DialogSingleChoiceItem( modifier: Modifier = Modifier, text: String, selected: Boolean, @@ -69,15 +69,18 @@ fun SingleChoiceItem( fun SingleChoiceItemPreview() { Surface { Column { - SingleChoiceItemWithLabel( + DialogSingleChoiceItemWithLabel( text = "Better compatibility", label = "For sharing to other apps", selected = false ) { } - SingleChoiceItemWithLabel( + DialogSingleChoiceItemWithLabel( text = "Better quality", label = "For watching in compatible apps", selected = true ) { + } + DialogSingleChoiceItem(text = "Preview", selected = true) { + } } @@ -86,7 +89,7 @@ fun SingleChoiceItemPreview() { } @Composable -fun SingleChoiceItemWithLabel( +fun DialogSingleChoiceItemWithLabel( modifier: Modifier = Modifier, text: String, label: String?, @@ -157,7 +160,7 @@ fun CheckBoxItem( } @Composable -fun SwitchItem( +fun DialogSwitchItem( modifier: Modifier = Modifier, text: String, value: Boolean, @@ -209,7 +212,7 @@ fun SwitchItem( private fun SwitchItemPrev() { var value by remember { mutableStateOf(false) } Surface { - SwitchItem(text = "Use cookies", value = value) { + DialogSwitchItem(text = "Use cookies", value = value) { value = it } } diff --git a/app/src/main/java/com/junkfood/seal/ui/component/Dialogs.kt b/app/src/main/java/com/junkfood/seal/ui/component/Dialogs.kt index a90e4f698a..d32632799e 100644 --- a/app/src/main/java/com/junkfood/seal/ui/component/Dialogs.kt +++ b/app/src/main/java/com/junkfood/seal/ui/component/Dialogs.kt @@ -67,9 +67,9 @@ fun HelpDialog( @OptIn(ExperimentalMaterial3Api::class) @Composable fun SealDialog( - onDismissRequest: () -> Unit, - confirmButton: @Composable () -> Unit, modifier: Modifier = Modifier, + onDismissRequest: () -> Unit, + confirmButton: @Composable (() -> Unit)?, dismissButton: @Composable (() -> Unit)? = null, icon: @Composable (() -> Unit)? = null, title: @Composable (() -> Unit)? = null, @@ -159,7 +159,7 @@ fun SealDialog( crossAxisSpacing = ButtonsCrossAxisSpacing ) { dismissButton?.invoke() - confirmButton() + confirmButton?.invoke() } } } diff --git a/app/src/main/java/com/junkfood/seal/ui/component/PreferenceItems.kt b/app/src/main/java/com/junkfood/seal/ui/component/PreferenceItems.kt index 9f375bbaa1..41491b1e0d 100644 --- a/app/src/main/java/com/junkfood/seal/ui/component/PreferenceItems.kt +++ b/app/src/main/java/com/junkfood/seal/ui/component/PreferenceItems.kt @@ -154,9 +154,18 @@ fun PreferenceItem( @Composable @Preview fun PreferenceItemPreview() { - Column { - PreferenceItem(title = "title", description = "description", icon = 0) - PreferenceItem(title = "title", description = "description", icon = Icons.Outlined.Update) + SealTheme { + Surface { + Column { + PreferenceSubtitle(text = "Preview") + PreferenceItem(title = "title", description = "description") + PreferenceItem( + title = "title", + description = "description", + icon = Icons.Outlined.Update + ) + } + } } } @@ -834,7 +843,7 @@ fun TemplateItem( @Composable fun PreferenceSubtitle( modifier: Modifier = Modifier, - contentPadding: PaddingValues = PaddingValues(start = 18.dp, top = 24.dp, bottom = 12.dp), + contentPadding: PaddingValues = PaddingValues(start = 20.dp, top = 24.dp, bottom = 12.dp), text: String, color: Color = MaterialTheme.colorScheme.primary, ) { diff --git a/app/src/main/java/com/junkfood/seal/ui/page/download/DownloadSettingsDialog.kt b/app/src/main/java/com/junkfood/seal/ui/page/download/DownloadSettingsDialog.kt index 3c9ba25b30..d3ea06d131 100644 --- a/app/src/main/java/com/junkfood/seal/ui/page/download/DownloadSettingsDialog.kt +++ b/app/src/main/java/com/junkfood/seal/ui/page/download/DownloadSettingsDialog.kt @@ -1,6 +1,10 @@ package com.junkfood.seal.ui.page.download +import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeOut +import androidx.compose.animation.togetherWith import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -12,7 +16,6 @@ import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.AudioFile import androidx.compose.material.icons.outlined.Cancel @@ -53,7 +56,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.junkfood.seal.R import com.junkfood.seal.ui.common.booleanState import com.junkfood.seal.ui.common.intState -import com.junkfood.seal.ui.common.stringState +import com.junkfood.seal.ui.common.motion.materialSharedAxisYIn import com.junkfood.seal.ui.component.ButtonChip import com.junkfood.seal.ui.component.DismissButton import com.junkfood.seal.ui.component.DrawerSheetSubtitle @@ -78,6 +81,7 @@ import com.junkfood.seal.util.CONVERT_M4A import com.junkfood.seal.util.CONVERT_MP3 import com.junkfood.seal.util.COOKIES import com.junkfood.seal.util.CUSTOM_COMMAND +import com.junkfood.seal.util.DOWNLOAD_TYPE_INITIALIZATION import com.junkfood.seal.util.DatabaseUtil import com.junkfood.seal.util.DownloadUtil import com.junkfood.seal.util.DownloadUtil.toFormatSorter @@ -99,12 +103,18 @@ import com.junkfood.seal.util.SORTING_FIELDS import com.junkfood.seal.util.SUBTITLE import com.junkfood.seal.util.TEMPLATE_ID import com.junkfood.seal.util.THUMBNAIL +import com.junkfood.seal.util.USE_PREVIOUS_SELECTION import com.junkfood.seal.util.VIDEO_FORMAT import com.junkfood.seal.util.VIDEO_QUALITY import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext + +private enum class DownloadType { + AUDIO, VIDEO, COMMAND, NONE +} + @OptIn( ExperimentalMaterial3Api::class, ) @@ -118,9 +128,9 @@ fun DownloadSettingDialog( onDownloadConfirm: () -> Unit, onDismissRequest: () -> Unit, ) { - var audio by remember { mutableStateOf(PreferenceUtil.getValue(EXTRACT_AUDIO)) } +// val audio by remember { mutableStateOf(PreferenceUtil.getValue(EXTRACT_AUDIO)) } + var thumbnail by remember { mutableStateOf(PreferenceUtil.getValue(THUMBNAIL)) } - var customCommand by remember { mutableStateOf(PreferenceUtil.getValue(CUSTOM_COMMAND)) } var playlist by remember { mutableStateOf(PreferenceUtil.getValue(PLAYLIST)) } var subtitle by remember { mutableStateOf(PreferenceUtil.getValue(SUBTITLE)) } var formatSelection by FORMAT_SELECTION.booleanState @@ -129,6 +139,27 @@ fun DownloadSettingDialog( var cookies by COOKIES.booleanState var formatSorting by FORMAT_SORTING.booleanState + var type by remember(showDialog) { + mutableStateOf( + when (DOWNLOAD_TYPE_INITIALIZATION.getInt()) { + USE_PREVIOUS_SELECTION -> { + if (CUSTOM_COMMAND.getBoolean()) { + DownloadType.COMMAND + } else if (EXTRACT_AUDIO.getBoolean()) { + DownloadType.AUDIO + } else { + DownloadType.VIDEO + } + } + + else -> { + DownloadType.NONE + } + } + ) + } + + var showAudioSettingsDialog by remember { mutableStateOf(false) } var showVideoQualityDialog by remember { mutableStateOf(false) } var showVideoFormatDialog by remember { mutableStateOf(false) } @@ -166,9 +197,9 @@ fun DownloadSettingDialog( val updatePreferences = { scope.launch { - PreferenceUtil.updateValue(EXTRACT_AUDIO, audio) + PreferenceUtil.updateValue(EXTRACT_AUDIO, type == DownloadType.AUDIO) PreferenceUtil.updateValue(THUMBNAIL, thumbnail) - PreferenceUtil.updateValue(CUSTOM_COMMAND, customCommand) + PreferenceUtil.updateValue(CUSTOM_COMMAND, type == DownloadType.COMMAND) PreferenceUtil.updateValue(PLAYLIST, playlist) PreferenceUtil.updateValue(SUBTITLE, subtitle) } @@ -197,34 +228,29 @@ fun DownloadSettingDialog( // .horizontalScroll(rememberScrollState()) ) { - val audioSelected by remember { derivedStateOf { audio && !customCommand } } - val videoSelected by remember { derivedStateOf { !audio && !customCommand } } - val commandSelected by remember { derivedStateOf { customCommand } } SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) { SingleChoiceSegmentedButton( text = stringResource(id = R.string.audio), - selected = audioSelected, + selected = type == DownloadType.AUDIO, position = SegmentedButtonValues.START ) { - audio = true - customCommand = false + type = DownloadType.AUDIO updatePreferences() } SingleChoiceSegmentedButton( text = stringResource(id = R.string.video), - selected = videoSelected + selected = type == DownloadType.VIDEO ) { - audio = false - customCommand = false + type = DownloadType.VIDEO updatePreferences() } SingleChoiceSegmentedButton( text = stringResource(id = R.string.commands), - selected = commandSelected, + selected = type == DownloadType.COMMAND, position = SegmentedButtonValues.END ) { - customCommand = true + type = DownloadType.COMMAND updatePreferences() } } @@ -236,7 +262,7 @@ fun DownloadSettingDialog( selected = !formatSelection || playlist, onClick = { formatSelection = false FORMAT_SELECTION.updateBoolean(false) - }, enabled = !customCommand, + }, enabled = type != DownloadType.COMMAND, label = stringResource(id = R.string.auto) ) SingleChoiceChip( @@ -245,102 +271,122 @@ fun DownloadSettingDialog( formatSelection = true FORMAT_SELECTION.updateBoolean(true) }, - enabled = !customCommand && !playlist, + enabled = type != DownloadType.COMMAND && !playlist, label = stringResource(id = R.string.custom) ) } } - DrawerSheetSubtitle(text = stringResource(id = if (customCommand) R.string.template_selection else R.string.format_preference)) - AnimatedVisibility(visible = !customCommand) { - - Row( - modifier = Modifier - .fillMaxWidth() - .horizontalScroll(rememberScrollState()) - ) { - if (!audio) { - ButtonChip( - onClick = { - showVideoFormatDialog = true - }, - enabled = !customCommand && !formatSorting, - label = PreferenceStrings.getVideoFormatLabel(videoFormatPreference), - icon = Icons.Outlined.VideoFile, - iconDescription = stringResource(id = R.string.video_format_preference) - ) - ButtonChip( - label = PreferenceStrings.getVideoResolutionDescComp(), - icon = Icons.Outlined.HighQuality, - enabled = !customCommand && !formatSorting, - iconDescription = stringResource(id = R.string.video_quality) + DrawerSheetSubtitle(text = stringResource(id = if (type == DownloadType.COMMAND) R.string.template_selection else R.string.format_preference)) + AnimatedContent(targetState = type, label = "", transitionSpec = { + (materialSharedAxisYIn(initialOffsetX = { it / 4 })).togetherWith( + fadeOut(tween(durationMillis = 80)) + ) + }) { type -> + when (type) { + DownloadType.COMMAND -> { + LazyRow( + modifier = Modifier, ) { - showVideoQualityDialog = true + item { + ButtonChip( + icon = Icons.Outlined.Code, + label = template.name, + onClick = { showTemplateSelectionDialog = true } + ) + } + item { + ButtonChip( + icon = Icons.Outlined.NewLabel, + label = stringResource(id = R.string.new_template), + onClick = { showTemplateCreatorDialog = true } + ) + } + item { + ButtonChip( + icon = Icons.Outlined.Edit, + label = stringResource( + id = R.string.edit_template, + template.name + ), + onClick = { showTemplateEditorDialog = true } + ) + } } } - ButtonChip( - onClick = { - showAudioSettingsDialog = true - }, - enabled = !customCommand && !formatSorting, - label = stringResource(R.string.audio_format), - icon = Icons.Outlined.AudioFile - ) - val convertToMp3 = stringResource(id = R.string.convert_to, "mp3") - val convertToM4a = stringResource(id = R.string.convert_to, "m4a") - val notConvert = stringResource(id = R.string.not_convert) - - if (audio) { - val convertAudioLabelText by remember(showAudioConversionDialog, audio) { - derivedStateOf { - if (!AUDIO_CONVERT.getBoolean()) { - notConvert - } else { - val format = AUDIO_CONVERSION_FORMAT.getInt() - when (format) { - CONVERT_MP3 -> convertToMp3 - CONVERT_M4A -> convertToM4a - else -> notConvert + + else -> { + Row( + modifier = Modifier + .fillMaxWidth() + .horizontalScroll(rememberScrollState()) + ) { + if (type != DownloadType.AUDIO) { + ButtonChip( + onClick = { + showVideoFormatDialog = true + }, + enabled = !formatSorting && type != DownloadType.NONE, + label = PreferenceStrings.getVideoFormatLabel( + videoFormatPreference + ), + icon = Icons.Outlined.VideoFile, + iconDescription = stringResource(id = R.string.video_format_preference) + ) + ButtonChip( + label = PreferenceStrings.getVideoResolutionDescComp(), + icon = Icons.Outlined.HighQuality, + enabled = !formatSorting && type != DownloadType.NONE, + iconDescription = stringResource(id = R.string.video_quality) + ) { + showVideoQualityDialog = true + } + } + ButtonChip( + onClick = { + showAudioSettingsDialog = true + }, + enabled = !formatSorting && type != DownloadType.NONE, + label = stringResource(R.string.audio_format), + icon = Icons.Outlined.AudioFile + ) + val convertToMp3 = stringResource(id = R.string.convert_to, "mp3") + val convertToM4a = stringResource(id = R.string.convert_to, "m4a") + val notConvert = stringResource(id = R.string.not_convert) + + if (type == DownloadType.AUDIO) { + val convertAudioLabelText by remember( + showAudioConversionDialog, + type + ) { + derivedStateOf { + if (!AUDIO_CONVERT.getBoolean()) { + notConvert + } else { + val format = AUDIO_CONVERSION_FORMAT.getInt() + when (format) { + CONVERT_MP3 -> convertToMp3 + CONVERT_M4A -> convertToM4a + else -> notConvert + } + } } } + ButtonChip( + label = convertAudioLabelText, + icon = Icons.Outlined.Sync, + ) { + showAudioConversionDialog = true + } } } - ButtonChip( - label = convertAudioLabelText, - icon = Icons.Outlined.Sync - ) { - showAudioConversionDialog = true - } } } + } - AnimatedVisibility(visible = customCommand) { - LazyRow( - modifier = Modifier, -// horizontalArrangement = Arrangement.spacedBy(4.dp) - ) { - item { - ButtonChip( - icon = Icons.Outlined.Code, - label = template.name, - onClick = { showTemplateSelectionDialog = true } - ) - } - item { - ButtonChip( - icon = Icons.Outlined.NewLabel, - label = stringResource(id = R.string.new_template), - onClick = { showTemplateCreatorDialog = true } - ) - } - item { - ButtonChip( - icon = Icons.Outlined.Edit, - label = stringResource(id = R.string.edit_template, template.name), - onClick = { showTemplateEditorDialog = true } - ) - } - } + + AnimatedVisibility(visible = type == DownloadType.COMMAND) { + } @@ -369,7 +415,7 @@ fun DownloadSettingDialog( FilterChip( modifier = Modifier.padding(horizontal = 4.dp), selected = formatSorting, - enabled = !customCommand, + enabled = type != DownloadType.COMMAND, onClick = { showFormatSortingDialog = true }, label = { Text(text = stringResource(id = R.string.format_sorting)) @@ -378,7 +424,7 @@ fun DownloadSettingDialog( } if (!isQuickDownload) { VideoFilterChip( - selected = playlist, enabled = !customCommand, onClick = { + selected = playlist, enabled = type != DownloadType.COMMAND, onClick = { playlist = !playlist formatSelection = false updatePreferences() @@ -386,13 +432,13 @@ fun DownloadSettingDialog( ) } VideoFilterChip( - selected = subtitle, enabled = !customCommand, onClick = { + selected = subtitle, enabled = type != DownloadType.COMMAND, onClick = { subtitle = !subtitle updatePreferences() }, label = stringResource(id = R.string.download_subtitles) ) VideoFilterChip( - selected = thumbnail, enabled = !customCommand, onClick = { + selected = thumbnail, enabled = type != DownloadType.COMMAND, onClick = { thumbnail = !thumbnail updatePreferences() }, label = stringResource(R.string.create_thumbnail) @@ -450,7 +496,8 @@ fun DownloadSettingDialog( FilledButtonWithIcon( onClick = downloadButtonCallback, icon = Icons.Outlined.DownloadDone, - text = stringResource(R.string.start_download) + text = stringResource(R.string.start_download), + enabled = type != DownloadType.NONE ) } } @@ -502,7 +549,7 @@ fun DownloadSettingDialog( if (showTemplateSelectionDialog) { - TemplatePickerDialog() { showTemplateSelectionDialog = false } + TemplatePickerDialog { showTemplateSelectionDialog = false } } if (showTemplateCreatorDialog) { CommandTemplateDialog( diff --git a/app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/AppearancePreferences.kt b/app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/AppearancePreferences.kt index 9a48c9be72..b67bc1aa93 100644 --- a/app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/AppearancePreferences.kt +++ b/app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/AppearancePreferences.kt @@ -27,7 +27,6 @@ import androidx.compose.material.icons.outlined.Colorize import androidx.compose.material.icons.outlined.DarkMode import androidx.compose.material.icons.outlined.Language import androidx.compose.material.icons.outlined.LightMode -import androidx.compose.material.icons.outlined.Palette import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -42,6 +41,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -64,14 +64,19 @@ import com.junkfood.seal.ui.common.Route import com.junkfood.seal.ui.component.BackButton import com.junkfood.seal.ui.component.LargeTopAppBar import com.junkfood.seal.ui.component.PreferenceItem +import com.junkfood.seal.ui.component.PreferenceSubtitle import com.junkfood.seal.ui.component.PreferenceSwitch import com.junkfood.seal.ui.component.PreferenceSwitchWithDivider import com.junkfood.seal.ui.component.VideoCard +import com.junkfood.seal.util.DOWNLOAD_TYPE_INITIALIZATION import com.junkfood.seal.util.DarkThemePreference.Companion.OFF import com.junkfood.seal.util.DarkThemePreference.Companion.ON import com.junkfood.seal.util.PreferenceUtil +import com.junkfood.seal.util.PreferenceUtil.getInt +import com.junkfood.seal.util.PreferenceUtil.updateInt import com.junkfood.seal.util.STYLE_MONOCHROME import com.junkfood.seal.util.STYLE_TONAL_SPOT +import com.junkfood.seal.util.USE_PREVIOUS_SELECTION import com.junkfood.seal.util.getLanguageDesc import com.junkfood.seal.util.paletteStyles import com.kyant.monet.LocalTonalPalettes @@ -103,6 +108,13 @@ fun AppearancePreferences( ) } + var showDownloadTypeDialog by remember { mutableStateOf(false) } + val initialType by remember(showDownloadTypeDialog) { + mutableIntStateOf( + DOWNLOAD_TYPE_INITIALIZATION.getInt() + ) + } + Scaffold(modifier = Modifier .fillMaxSize() .nestedScroll(scrollBehavior.nestedScrollConnection), @@ -181,7 +193,6 @@ fun AppearancePreferences( inactiveColor = MaterialTheme.colorScheme.outlineVariant, indicatorHeight = 6.dp, indicatorWidth = 6.dp) - if (DynamicColors.isDynamicColorAvailable()) { PreferenceSwitch(title = stringResource(id = R.string.dynamic_color), description = stringResource( @@ -205,8 +216,29 @@ fun AppearancePreferences( icon = Icons.Outlined.Language, description = getLanguageDesc() ) { navController.navigate(Route.LANGUAGES) } + PreferenceSubtitle(text = stringResource(id = R.string.settings_before_download)) + + PreferenceItem( + title = stringResource(id = R.string.download_type), + description = when (initialType) { + USE_PREVIOUS_SELECTION -> stringResource(id = R.string.use_previous_selection) + else -> stringResource(id = R.string.none) + } + ) { + showDownloadTypeDialog = true + } } }) + + if (showDownloadTypeDialog) { + DownloadTypeCustomizationDialog( + onDismissRequest = { showDownloadTypeDialog = false }, + selectedItem = initialType + ) { + DOWNLOAD_TYPE_INITIALIZATION.updateInt(it) + showDownloadTypeDialog = false + } + } } @Composable diff --git a/app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/InterfaceCustomizationDialogs.kt b/app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/InterfaceCustomizationDialogs.kt new file mode 100644 index 0000000000..30714daf7c --- /dev/null +++ b/app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/InterfaceCustomizationDialogs.kt @@ -0,0 +1,60 @@ +package com.junkfood.seal.ui.page.settings.appearance + +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.junkfood.seal.R +import com.junkfood.seal.ui.component.DialogSingleChoiceItem +import com.junkfood.seal.ui.component.SealDialog +import com.junkfood.seal.util.NONE +import com.junkfood.seal.util.USE_PREVIOUS_SELECTION + +@Composable +fun DownloadTypeCustomizationDialog( + modifier: Modifier = Modifier, + onDismissRequest: () -> Unit, + selectedItem: Int, + onSelect: (Int) -> Unit +) { + SealDialog( + modifier = modifier, + onDismissRequest = onDismissRequest, + confirmButton = null, + title = { + Text(text = stringResource(id = R.string.download_type)) + }, + text = { + LazyColumn(modifier = Modifier.padding()) { + item { + DialogSingleChoiceItem( + text = stringResource(id = R.string.use_previous_selection), + selected = selectedItem == USE_PREVIOUS_SELECTION + ) { + onSelect(USE_PREVIOUS_SELECTION) + } + } + + item { + DialogSingleChoiceItem( + text = stringResource(id = R.string.none), + selected = selectedItem == NONE + ) { + onSelect(NONE) + } + } + } + }) +} + +@Preview +@Composable +private fun Preview() { + DownloadTypeCustomizationDialog(onDismissRequest = {}, selectedItem = NONE) { + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/junkfood/seal/ui/page/settings/directory/DownloadDirectoryPreferences.kt b/app/src/main/java/com/junkfood/seal/ui/page/settings/directory/DownloadDirectoryPreferences.kt index 14b8158519..a6fd48e33e 100644 --- a/app/src/main/java/com/junkfood/seal/ui/page/settings/directory/DownloadDirectoryPreferences.kt +++ b/app/src/main/java/com/junkfood/seal/ui/page/settings/directory/DownloadDirectoryPreferences.kt @@ -90,7 +90,7 @@ import com.junkfood.seal.ui.component.PreferenceSwitch import com.junkfood.seal.ui.component.PreferenceSwitchWithDivider import com.junkfood.seal.ui.component.PreferencesHintCard import com.junkfood.seal.ui.component.SealDialog -import com.junkfood.seal.ui.component.SingleChoiceItem +import com.junkfood.seal.ui.component.DialogSingleChoiceItem import com.junkfood.seal.util.COMMAND_DIRECTORY import com.junkfood.seal.util.CUSTOM_COMMAND import com.junkfood.seal.util.CUSTOM_OUTPUT_TEMPLATE @@ -582,13 +582,13 @@ fun OutputTemplateDialog( fontFamily = FontFamily.Monospace, ) ) { - SingleChoiceItem( + DialogSingleChoiceItem( text = DownloadUtil.OUTPUT_TEMPLATE_DEFAULT, selected = selectedItem == 1 ) { selectedItem = 1 } - SingleChoiceItem( + DialogSingleChoiceItem( text = DownloadUtil.OUTPUT_TEMPLATE_ID, selected = selectedItem == 2 ) { diff --git a/app/src/main/java/com/junkfood/seal/ui/page/settings/format/FormatSettingDialogs.kt b/app/src/main/java/com/junkfood/seal/ui/page/settings/format/FormatSettingDialogs.kt index 98c1dd2f9d..bd80e8dee9 100644 --- a/app/src/main/java/com/junkfood/seal/ui/page/settings/format/FormatSettingDialogs.kt +++ b/app/src/main/java/com/junkfood/seal/ui/page/settings/format/FormatSettingDialogs.kt @@ -59,9 +59,9 @@ import com.junkfood.seal.ui.component.DismissButton import com.junkfood.seal.ui.component.HorizontalDivider import com.junkfood.seal.ui.component.OutlinedButtonChip import com.junkfood.seal.ui.component.SealDialog -import com.junkfood.seal.ui.component.SingleChoiceItem -import com.junkfood.seal.ui.component.SingleChoiceItemWithLabel -import com.junkfood.seal.ui.component.SwitchItem +import com.junkfood.seal.ui.component.DialogSingleChoiceItem +import com.junkfood.seal.ui.component.DialogSingleChoiceItemWithLabel +import com.junkfood.seal.ui.component.DialogSwitchItem import com.junkfood.seal.util.AUDIO_CONVERSION_FORMAT import com.junkfood.seal.util.AUDIO_CONVERT import com.junkfood.seal.util.AUDIO_FORMAT @@ -357,7 +357,7 @@ fun AudioConversionDialog( style = MaterialTheme.typography.bodyLarge ) for (i in CONVERT_MP3..CONVERT_M4A) - SingleChoiceItem( + DialogSingleChoiceItem( modifier = Modifier, text = PreferenceStrings.getAudioConvertDesc(i), selected = audioFormat == i @@ -399,14 +399,14 @@ fun AudioConversionQuickSettingsDialog( text = stringResource(R.string.convert_audio_format_desc), style = MaterialTheme.typography.bodyLarge ) - SingleChoiceItem( + DialogSingleChoiceItem( text = stringResource(id = R.string.not_convert), selected = !convertAudio ) { convertAudio = false } for (i in CONVERT_MP3..CONVERT_M4A) - SingleChoiceItem( + DialogSingleChoiceItem( modifier = Modifier, text = PreferenceStrings.getAudioConvertDesc(i), selected = audioFormat == i && convertAudio @@ -453,7 +453,7 @@ fun VideoFormatDialog( for (i in listOf(FORMAT_COMPATIBILITY, FORMAT_QUALITY)) item { - SingleChoiceItemWithLabel( + DialogSingleChoiceItemWithLabel( modifier = Modifier, text = PreferenceStrings.getVideoFormatLabel(i), label = PreferenceStrings.getVideoFormatDescComp(i), @@ -496,7 +496,7 @@ fun AudioFormatDialog(onDismissRequest: () -> Unit) { style = MaterialTheme.typography.bodyLarge ) for (i in DEFAULT..M4A) - SingleChoiceItem( + DialogSingleChoiceItem( modifier = Modifier, text = PreferenceStrings.getAudioFormatDesc(i), selected = audioFormat == i @@ -531,7 +531,7 @@ fun AudioQualityDialog(onDismissRequest: () -> Unit) { style = MaterialTheme.typography.bodyLarge ) for (i in NOT_SPECIFIED..ULTRA_LOW) - SingleChoiceItem( + DialogSingleChoiceItem( modifier = Modifier, text = PreferenceStrings.getAudioQualityDesc(i), selected = audioQuality == i @@ -608,7 +608,7 @@ fun FormatSortingDialog( if (showSwitch) { Spacer(modifier = Modifier.height(12.dp)) HorizontalDivider(modifier = Modifier.padding(horizontal = 24.dp)) - SwitchItem( + DialogSwitchItem( text = stringResource(id = R.string.use_format_sorting), value = toggleableValue, onValueChange = onSwitchChecked @@ -668,7 +668,7 @@ fun VideoQualityDialog( // item { videoResolutionSelectField() } for (i in 0..7) { item { - SingleChoiceItem( + DialogSingleChoiceItem( text = PreferenceStrings.getVideoResolutionDesc(i), selected = videoResolution == i ) { @@ -794,7 +794,7 @@ fun SubtitleConversionDialog(onDismissRequest: () -> Unit) { } for (format in NOT_CONVERT..CONVERT_VTT) { item { - SingleChoiceItem( + DialogSingleChoiceItem( text = PreferenceStrings.getSubtitleConversionFormat(format), selected = currentFormat == format ) { diff --git a/app/src/main/java/com/junkfood/seal/ui/page/settings/network/CookieProfilesPage.kt b/app/src/main/java/com/junkfood/seal/ui/page/settings/network/CookieProfilesPage.kt index cf17484047..1cb6338ff2 100644 --- a/app/src/main/java/com/junkfood/seal/ui/page/settings/network/CookieProfilesPage.kt +++ b/app/src/main/java/com/junkfood/seal/ui/page/settings/network/CookieProfilesPage.kt @@ -85,7 +85,7 @@ import com.junkfood.seal.ui.component.PasteFromClipBoardButton import com.junkfood.seal.ui.component.PreferenceItemVariant import com.junkfood.seal.ui.component.PreferenceSwitchWithContainer import com.junkfood.seal.ui.component.SealDialog -import com.junkfood.seal.ui.component.SwitchItem +import com.junkfood.seal.ui.component.DialogSwitchItem import com.junkfood.seal.ui.component.TextButtonWithIcon import com.junkfood.seal.ui.theme.SealTheme import com.junkfood.seal.ui.theme.generateLabelColor @@ -485,7 +485,7 @@ fun CookiesQuickSettingsDialog( } Spacer(modifier = Modifier.height(4.dp)) HorizontalDivider(Modifier.padding(horizontal = 24.dp)) - SwitchItem( + DialogSwitchItem( text = stringResource(id = R.string.use_cookies), value = isCookiesEnabled, onValueChange = onCookiesToggled diff --git a/app/src/main/java/com/junkfood/seal/util/PreferenceUtil.kt b/app/src/main/java/com/junkfood/seal/util/PreferenceUtil.kt index a8e6a772e3..0ba4b05b2d 100644 --- a/app/src/main/java/com/junkfood/seal/util/PreferenceUtil.kt +++ b/app/src/main/java/com/junkfood/seal/util/PreferenceUtil.kt @@ -103,10 +103,15 @@ const val FORCE_IPV4 = "force_ipv4" const val MERGE_MULTI_AUDIO_STREAM = "multi_audio_stream" -const val DEFAULT = 0 +const val DOWNLOAD_TYPE_INITIALIZATION = "download_type_init" + const val NOT_SPECIFIED = 0 -const val SYSTEM_DEFAULT = 0 -const val NOT_CONVERT = 0 +const val DEFAULT = NOT_SPECIFIED +const val SYSTEM_DEFAULT = NOT_SPECIFIED +const val NOT_CONVERT = NOT_SPECIFIED + +const val NONE = NOT_SPECIFIED +const val USE_PREVIOUS_SELECTION = 1 const val CONVERT_ASS = 1 const val CONVERT_LRC = 2 @@ -181,6 +186,7 @@ private val IntPreferenceDefaults = mapOf( UPDATE_CHANNEL to STABLE, SHOW_SPONSOR_MSG to 0, CONVERT_SUBTITLE to NOT_SPECIFIED, + DOWNLOAD_TYPE_INITIALIZATION to USE_PREVIOUS_SELECTION, ) fun String.getStringDefault() = StringPreferenceDefaults.getOrElse(this) { "" } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ec5a403353..270a20cfb4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -417,7 +417,9 @@ Auto-translated subtitles for all languages will be available in downloads. These subtitles may be inaccurate and difficult to understand. Language of the subtitles to download in Auto format selection, separated by commas. Remember for next download - + + + Use previous selection None @@ -439,7 +441,7 @@ Import download history? Downloaded files won\'t be imported. You\'ll need to download them back manually Exporting %1$s from download history. Downloaded files and preferences won\'t be backed up. - + Download history %d item %d items