diff --git a/app/src/main/java/au/com/shiftyjelly/pocketcasts/ui/MainActivity.kt b/app/src/main/java/au/com/shiftyjelly/pocketcasts/ui/MainActivity.kt index 85496b3209f..1fc7e1a65ff 100644 --- a/app/src/main/java/au/com/shiftyjelly/pocketcasts/ui/MainActivity.kt +++ b/app/src/main/java/au/com/shiftyjelly/pocketcasts/ui/MainActivity.kt @@ -12,6 +12,7 @@ import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.widget.Toolbar +import androidx.compose.ui.res.stringResource import androidx.core.view.isVisible import androidx.core.view.updatePadding import androidx.fragment.app.Fragment @@ -26,6 +27,10 @@ import au.com.shiftyjelly.pocketcasts.account.PromoCodeUpgradedFragment import au.com.shiftyjelly.pocketcasts.analytics.AnalyticsEvent import au.com.shiftyjelly.pocketcasts.analytics.AnalyticsTrackerWrapper import au.com.shiftyjelly.pocketcasts.analytics.FirebaseAnalyticsTracker +import au.com.shiftyjelly.pocketcasts.compose.AppTheme +import au.com.shiftyjelly.pocketcasts.compose.bottomsheet.BottomSheetContentState +import au.com.shiftyjelly.pocketcasts.compose.bottomsheet.BottomSheetContentState.Content.Button +import au.com.shiftyjelly.pocketcasts.compose.bottomsheet.ModalBottomSheet import au.com.shiftyjelly.pocketcasts.databinding.ActivityMainBinding import au.com.shiftyjelly.pocketcasts.discover.view.DiscoverFragment import au.com.shiftyjelly.pocketcasts.filters.FiltersFragment @@ -249,6 +254,10 @@ class MainActivity : handleIntent(intent, savedInstanceState) updateSystemColors() + + if (BuildConfig.END_OF_YEAR_ENABLED) { + setupEndOfYearLaunchBottomSheet() + } } override fun onStart() { @@ -446,6 +455,27 @@ class MainActivity : showBottomSheet(UpNextFragment.newInstance(source = source)) } + private fun setupEndOfYearLaunchBottomSheet() { + binding.modalBottomSheet.setContent { + AppTheme(themeType = theme.activeTheme) { + ModalBottomSheet( + showOnLoad = true, + content = BottomSheetContentState.Content( + titleText = stringResource(LR.string.end_of_year_launch_modal_title), + summaryText = stringResource(LR.string.end_of_year_launch_modal_summary), + primaryButton = Button.Primary( + label = stringResource(LR.string.end_of_year_launch_modal_primary_button_title), + onClick = {} + ), + secondaryButton = Button.Secondary( + label = stringResource(LR.string.end_of_year_launch_modal_secondary_button_title), + ), + ) + ) + } + } + } + @OptIn(DelicateCoroutinesApi::class) @Suppress("DEPRECATION") private fun setupPlayerViews() { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index e79fec5d026..b7a99246bec 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -62,6 +62,12 @@ android:clickable="true" android:translationZ="200dp"/> + + Unit)? + + data class Primary( + override val label: String, + override val onClick: () -> Unit, + ) : Button + + data class Secondary( + override val label: String, + override val onClick: (() -> Unit)? = null, + ) : Button + } + } +} + +@Composable +fun BottomSheetContent( + state: BottomSheetContentState, + onDismiss: () -> Unit, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .fillMaxWidth() + .wrapContentWidth(unbounded = false) + .wrapContentHeight(unbounded = true) + .padding(24.dp) + ) { + Column( + modifier = modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + val content = state.content + + Spacer(modifier = modifier.height(16.dp)) + + TextH40( + text = content.titleText, + color = MaterialTheme.theme.colors.primaryText01, + ) + + Spacer(modifier = modifier.height(16.dp)) + + TextP50( + text = content.summaryText, + style = MaterialTheme.typography.body1, + color = MaterialTheme.theme.colors.primaryText02, + textAlign = TextAlign.Center + ) + + Spacer(modifier = modifier.height(16.dp)) + + Button(onClick = content.primaryButton.onClick) { + Text(text = content.primaryButton.label) + } + + Spacer(modifier = modifier.height(8.dp)) + + if (content.secondaryButton != null) { + OutlinedButton( + border = outlinedBorder, + onClick = { + onDismiss.invoke() + content.secondaryButton.onClick?.invoke() + } + ) { + Text(text = content.secondaryButton.label) + } + } + } + } +} + +@Preview(showBackground = true) +@Composable +private fun BottomSheetContentPreview( + @PreviewParameter(ThemePreviewParameterProvider::class) themeType: Theme.ThemeType, +) { + AppThemeWithBackground(themeType) { + BottomSheetContent( + state = BottomSheetContentState( + content = BottomSheetContentState.Content( + titleText = "Heading", + summaryText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.", + primaryButton = BottomSheetContentState.Content.Button.Primary( + label = "Confirm", + onClick = {} + ), + secondaryButton = BottomSheetContentState.Content.Button.Secondary( + label = "Not now", + ), + ) + ), + onDismiss = {} + ) + } +} diff --git a/modules/services/compose/src/main/java/au/com/shiftyjelly/pocketcasts/compose/bottomsheet/ModalBottomSheet.kt b/modules/services/compose/src/main/java/au/com/shiftyjelly/pocketcasts/compose/bottomsheet/ModalBottomSheet.kt new file mode 100644 index 00000000000..7befed55269 --- /dev/null +++ b/modules/services/compose/src/main/java/au/com/shiftyjelly/pocketcasts/compose/bottomsheet/ModalBottomSheet.kt @@ -0,0 +1,53 @@ +package au.com.shiftyjelly.pocketcasts.compose.bottomsheet + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ModalBottomSheetLayout +import androidx.compose.material.ModalBottomSheetState +import androidx.compose.material.ModalBottomSheetValue +import androidx.compose.material.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun ModalBottomSheet( + showOnLoad: Boolean = false, + content: BottomSheetContentState.Content, +) { + val sheetState = rememberModalBottomSheetState( + initialValue = if (showOnLoad) ModalBottomSheetValue.Expanded else ModalBottomSheetValue.Hidden, + ) + val coroutineScope = rememberCoroutineScope() + + BackHandler(sheetState.isVisible) { + hideBottomSheet(coroutineScope, sheetState) + } + + ModalBottomSheetLayout( + sheetState = sheetState, + sheetContent = { + BottomSheetContent( + state = BottomSheetContentState(content), + onDismiss = { + hideBottomSheet(coroutineScope, sheetState) + } + ) + }, + sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), + scrimColor = Color.Black.copy(alpha = .25f), + content = {} + ) +} + +@OptIn(ExperimentalMaterialApi::class) +fun hideBottomSheet(coroutineScope: CoroutineScope, sheetState: ModalBottomSheetState) { + coroutineScope.launch { + sheetState.hide() + } +} diff --git a/modules/services/compose/src/main/java/au/com/shiftyjelly/pocketcasts/compose/components/TextStyles.kt b/modules/services/compose/src/main/java/au/com/shiftyjelly/pocketcasts/compose/components/TextStyles.kt index ff4897ac235..56620e7529e 100644 --- a/modules/services/compose/src/main/java/au/com/shiftyjelly/pocketcasts/compose/components/TextStyles.kt +++ b/modules/services/compose/src/main/java/au/com/shiftyjelly/pocketcasts/compose/components/TextStyles.kt @@ -130,14 +130,16 @@ fun TextP50( modifier: Modifier = Modifier, color: Color? = null, maxLines: Int? = null, - style: TextStyle? = null + style: TextStyle? = null, + textAlign: TextAlign? = null, ) { TextP50( text = AnnotatedString(text), modifier = modifier, color = color, maxLines = maxLines, - style = style + style = style, + textAlign = textAlign, ) } @@ -147,7 +149,8 @@ fun TextP50( modifier: Modifier = Modifier, color: Color? = null, maxLines: Int? = null, - style: TextStyle? = null + style: TextStyle? = null, + textAlign: TextAlign? = null, ) { Text( text = text, @@ -157,6 +160,7 @@ fun TextP50( maxLines = maxLines ?: Int.MAX_VALUE, overflow = TextOverflow.Ellipsis, style = style ?: LocalTextStyle.current, + textAlign = textAlign, modifier = modifier ) } diff --git a/modules/services/localization/src/main/res/values/strings.xml b/modules/services/localization/src/main/res/values/strings.xml index bd50f74f81e..d6fa6be4df1 100644 --- a/modules/services/localization/src/main/res/values/strings.xml +++ b/modules/services/localization/src/main/res/values/strings.xml @@ -1378,4 +1378,11 @@ You have exceeded the storage limit for your account. Title is required. + + + Your Year in Podcasts + See your top podcasts, categories, listening stats and more. Share with friends and shout out your favorite creators! + View my 2022 + Not Now +