Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

End of Year: Show profile card and badge #498

Merged
merged 7 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ 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
Expand All @@ -28,12 +27,10 @@ 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.endofyear.StoriesFragment
import au.com.shiftyjelly.pocketcasts.endofyear.views.EndOfYearLaunchBottomSheet
import au.com.shiftyjelly.pocketcasts.filters.FiltersFragment
import au.com.shiftyjelly.pocketcasts.localization.helper.LocaliseHelper
import au.com.shiftyjelly.pocketcasts.models.entity.Episode
Expand Down Expand Up @@ -186,6 +183,10 @@ class MainActivity :
val view = binding.root
setContentView(view)

if (BuildConfig.END_OF_YEAR_ENABLED && settings.getEndOfYearShowBadge2022()) {
binding.bottomNavigation.getOrCreateBadge(VR.id.navigation_profile)
}

var selectedTab = settings.selectedTab()
val tabs = mapOf(
VR.id.navigation_podcasts to { FragmentInfo(PodcastsFragment(), true) },
Expand Down Expand Up @@ -243,7 +244,11 @@ class MainActivity :
VR.id.navigation_podcasts -> FirebaseAnalyticsTracker.navigatedToPodcasts()
VR.id.navigation_filters -> FirebaseAnalyticsTracker.navigatedToFilters()
VR.id.navigation_discover -> FirebaseAnalyticsTracker.navigatedToDiscover()
VR.id.navigation_profile -> FirebaseAnalyticsTracker.navigatedToProfile()
VR.id.navigation_profile -> {
binding.bottomNavigation.removeBadge(VR.id.navigation_profile)
settings.setEndOfYearShowBadge2022(false)
FirebaseAnalyticsTracker.navigatedToProfile()
}
}
}
settings.setSelectedTab(currentTab)
Expand Down Expand Up @@ -459,22 +464,11 @@ class MainActivity :
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 = {
StoriesFragment.newInstance()
.show(supportFragmentManager, "stories_dialog")
}
),
secondaryButton = Button.Secondary(
label = stringResource(LR.string.end_of_year_launch_modal_secondary_button_title),
),
)
EndOfYearLaunchBottomSheet(
onClick = {
StoriesFragment.newInstance()
.show(supportFragmentManager, "stories_dialog")
}
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ import au.com.shiftyjelly.pocketcasts.endofyear.StoriesViewModel.State
import au.com.shiftyjelly.pocketcasts.endofyear.stories.Story
import au.com.shiftyjelly.pocketcasts.endofyear.stories.StoryFake1
import au.com.shiftyjelly.pocketcasts.endofyear.stories.StoryFake2
import au.com.shiftyjelly.pocketcasts.endofyear.storyviews.StoryFake1View
import au.com.shiftyjelly.pocketcasts.endofyear.storyviews.StoryFake2View
import au.com.shiftyjelly.pocketcasts.endofyear.views.StoryFake1View
import au.com.shiftyjelly.pocketcasts.endofyear.views.StoryFake2View
import au.com.shiftyjelly.pocketcasts.models.entity.Podcast
import au.com.shiftyjelly.pocketcasts.ui.theme.Theme
import au.com.shiftyjelly.pocketcasts.localization.R as LR
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package au.com.shiftyjelly.pocketcasts.endofyear.views

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import au.com.shiftyjelly.pocketcasts.compose.bottomsheet.BottomSheetContentState
import au.com.shiftyjelly.pocketcasts.compose.bottomsheet.ModalBottomSheet
import au.com.shiftyjelly.pocketcasts.localization.R as LR

@Composable
fun EndOfYearLaunchBottomSheet(
onClick: () -> Unit,
) {
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 = BottomSheetContentState.Content.Button.Primary(
label = stringResource(LR.string.end_of_year_launch_modal_primary_button_title),
onClick = { onClick.invoke() }
),
secondaryButton = BottomSheetContentState.Content.Button.Secondary(
label = stringResource(LR.string.end_of_year_launch_modal_secondary_button_title),
),
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package au.com.shiftyjelly.pocketcasts.endofyear.views

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import au.com.shiftyjelly.pocketcasts.compose.AppTheme
import au.com.shiftyjelly.pocketcasts.compose.components.TextH30
import au.com.shiftyjelly.pocketcasts.compose.components.TextH70
import au.com.shiftyjelly.pocketcasts.compose.preview.ThemePreviewParameterProvider
import au.com.shiftyjelly.pocketcasts.compose.theme
import au.com.shiftyjelly.pocketcasts.ui.theme.Theme
import au.com.shiftyjelly.pocketcasts.localization.R as LR

private val PromptCardCornerSize = 5.dp
private val PromptCardTextColor = Color.White

@Composable
fun EndOfYearPromptCard(
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier
.background(color = MaterialTheme.theme.colors.primaryUi02)
) {
Column(
modifier = modifier
.padding(horizontal = 16.dp, vertical = 8.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(PromptCardCornerSize))
.background(color = Color.Black)
.clickable { onClick.invoke() },
) {
TextH30(
text = stringResource(LR.string.end_of_year_prompt_card_title),
color = PromptCardTextColor,
modifier = modifier.padding(start = 16.dp, top = 16.dp, end = 16.dp, bottom = 8.dp)
)
TextH70(
text = stringResource(LR.string.end_of_year_prompt_card_summary),
color = PromptCardTextColor,
modifier = modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 16.dp)
)
}
}
}

@Preview(showBackground = true)
@Composable
private fun EndOfYearPromptCardPreview(
@PreviewParameter(ThemePreviewParameterProvider::class) themeType: Theme.ThemeType,
) {
AppTheme(themeType) {
EndOfYearPromptCard(onClick = {})
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package au.com.shiftyjelly.pocketcasts.endofyear.storyviews
package au.com.shiftyjelly.pocketcasts.endofyear.views

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package au.com.shiftyjelly.pocketcasts.endofyear.storyviews
package au.com.shiftyjelly.pocketcasts.endofyear.views

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class StoriesViewModelTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `when stories are found, then progress increments`() = runTest {
val storyLengthInMs = 2.seconds()
whenever(story1.storyLength).thenReturn(storyLengthInMs)
whenever(story2.storyLength).thenReturn(storyLengthInMs)
val viewModel = StoriesViewModel(MockStoriesDataSource(listOf(story1, story2)))

val progress = mutableListOf<Float>()
Expand Down
1 change: 1 addition & 0 deletions modules/features/profile/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies {
// features
implementation project(':modules:features:account')
implementation project(':modules:features:cartheme')
implementation project(':modules:features:endofyear')
implementation project(':modules:features:podcasts')
implementation project(':modules:features:settings')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import androidx.recyclerview.widget.RecyclerView
import au.com.shiftyjelly.pocketcasts.account.AccountActivity
import au.com.shiftyjelly.pocketcasts.analytics.AnalyticsEvent
import au.com.shiftyjelly.pocketcasts.analytics.AnalyticsTrackerWrapper
import au.com.shiftyjelly.pocketcasts.compose.AppTheme
import au.com.shiftyjelly.pocketcasts.endofyear.StoriesFragment
import au.com.shiftyjelly.pocketcasts.endofyear.views.EndOfYearPromptCard
import au.com.shiftyjelly.pocketcasts.localization.extensions.getStringPluralSecondsMinutesHoursDaysOrYears
import au.com.shiftyjelly.pocketcasts.models.to.RefreshState
import au.com.shiftyjelly.pocketcasts.podcasts.view.ProfileEpisodeListFragment
Expand Down Expand Up @@ -96,6 +99,10 @@ class ProfileFragment : BaseFragment() {

val binding = binding ?: return

if (BuildConfig.END_OF_YEAR_ENABLED) {
binding.setupEndOfYearPromptCard()
}

binding.btnSettings.setOnClickListener {
analyticsTracker.track(AnalyticsEvent.PROFILE_SETTINGS_BUTTON_TAPPED)
(activity as FragmentHostListener).addFragment(SettingsFragment())
Expand Down Expand Up @@ -216,6 +223,19 @@ class ProfileFragment : BaseFragment() {
}
}

private fun FragmentProfileBinding.setupEndOfYearPromptCard() {
endOfYearPromptCard.setContent {
AppTheme(theme.activeTheme) {
EndOfYearPromptCard(
onClick = {
StoriesFragment.newInstance()
.show(childFragmentManager, "stories_dialog")
}
)
}
}
}

private fun updateRefreshUI(state: RefreshState?) {
val binding = binding ?: return
val lblRefreshStatus = binding.lblRefreshStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,27 @@
app:layout_constraintStart_toStartOf="@+id/lblDaysSaved"
app:layout_constraintTop_toBottomOf="@+id/lblDaysSaved" />

<androidx.compose.ui.platform.ComposeView
android:id="@+id/endOfYearPromptCard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?attr/primary_ui_02"
android:paddingBottom="8dp"
android:paddingTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgBannerBackground" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?attr/primary_ui_02"
android:clipToPadding="false"
android:paddingTop="16dp"
android:paddingBottom="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imgBannerBackground" />
app:layout_constraintTop_toBottomOf="@id/endOfYearPromptCard" />

<TextView
android:id="@+id/lblRefreshStatus"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,27 @@
app:layout_constraintStart_toStartOf="@+id/lblDaysSaved"
app:layout_constraintTop_toBottomOf="@+id/lblDaysSaved" />

<androidx.compose.ui.platform.ComposeView
android:id="@+id/endOfYearPromptCard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:background="?attr/primary_ui_02"
android:paddingBottom="8dp"
android:paddingTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lblPodcastCountLabel" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:background="?attr/primary_ui_02"
android:clipToPadding="false"
android:paddingTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lblPodcastCountLabel" />
app:layout_constraintTop_toBottomOf="@+id/endOfYearPromptCard" />

<TextView
android:id="@+id/lblRefreshStatus"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1383,5 +1383,7 @@
<string name="end_of_year_launch_modal_summary">See your top podcasts, categories, listening stats and more. Share with friends and shout out your favorite creators!</string>
<string name="end_of_year_launch_modal_primary_button_title">View my 2022</string>
<string name="end_of_year_launch_modal_secondary_button_title">Not Now</string>
<string name="end_of_year_prompt_card_title" translatable="false">@string/end_of_year_launch_modal_title</string>
<string name="end_of_year_prompt_card_summary">See your top podcasts, categories, listening stats and more.</string>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -551,4 +551,7 @@ interface Settings {

fun setLinkCrashReportsToUser(value: Boolean)
fun getLinkCrashReportsToUser(): Boolean

fun setEndOfYearShowBadge2022(value: Boolean)
fun getEndOfYearShowBadge2022(): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class SettingsImpl @Inject constructor(
private const val SEND_USAGE_STATS_KEY = "SendUsageStatsKey"
private const val SEND_CRASH_REPORTS_KEY = "SendCrashReportsKey"
private const val LINK_CRASH_REPORTS_TO_USER_KEY = "LinkCrashReportsToUserKey"
private const val END_OF_YEAR_SHOW_BADGE_2022_KEY = "EndOfYearShowBadge2022Key"
}

private var languageCode: String? = null
Expand Down Expand Up @@ -1445,4 +1446,11 @@ class SettingsImpl @Inject constructor(

override fun getLinkCrashReportsToUser(): Boolean =
getBoolean(LINK_CRASH_REPORTS_TO_USER_KEY, false)

override fun setEndOfYearShowBadge2022(value: Boolean) {
setBoolean(END_OF_YEAR_SHOW_BADGE_2022_KEY, value)
}

override fun getEndOfYearShowBadge2022(): Boolean =
getBoolean(END_OF_YEAR_SHOW_BADGE_2022_KEY, true)
}