Skip to content

Commit

Permalink
Merge pull request #498 from Automattic/task/410-profile-card-and-badge
Browse files Browse the repository at this point in the history
End of Year: Show profile card and badge
  • Loading branch information
ashiagr authored Oct 27, 2022
2 parents 95a5324 + c9a27cb commit 1df40d5
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 30 deletions.
36 changes: 15 additions & 21 deletions app/src/main/java/au/com/shiftyjelly/pocketcasts/ui/MainActivity.kt
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
16 changes: 13 additions & 3 deletions modules/features/profile/src/main/res/layout/fragment_profile.xml
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
2 changes: 2 additions & 0 deletions modules/services/localization/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,8 @@
<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>

<!-- Tasker Plugin-->

Expand Down
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)
}

0 comments on commit 1df40d5

Please sign in to comment.