-
Notifications
You must be signed in to change notification settings - Fork 226
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #428 from Automattic/task/410-stories-structure
End of Year: Add stories structure
- Loading branch information
Showing
11 changed files
with
347 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
apply from: "../../modules.gradle" | ||
|
||
android { | ||
namespace 'au.com.shiftyjelly.pocketcasts.endofyear' | ||
buildFeatures { | ||
viewBinding true | ||
dataBinding = true | ||
compose true | ||
} | ||
} | ||
|
||
dependencies { | ||
// services | ||
implementation project(':modules:services:compose') | ||
implementation project(':modules:services:localization') | ||
implementation project(':modules:services:ui') | ||
implementation project(':modules:services:views') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
</manifest> |
78 changes: 78 additions & 0 deletions
78
...year/src/main/java/au/com/shiftyjelly/pocketcasts/endofyear/SegmentedProgressIndicator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package au.com.shiftyjelly.pocketcasts.endofyear | ||
|
||
import androidx.annotation.FloatRange | ||
import androidx.compose.foundation.Canvas | ||
import androidx.compose.foundation.focusable | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.progressSemantics | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.geometry.Offset | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.graphics.drawscope.DrawScope | ||
import androidx.compose.ui.unit.dp | ||
|
||
private val StrokeWidth = 2.dp | ||
private val GapWidth = 8.dp | ||
private val SegmentHeight = StrokeWidth | ||
private const val IndicatorBackgroundOpacity = 0.24f | ||
|
||
@Composable | ||
fun SegmentedProgressIndicator( | ||
@FloatRange(from = 0.0, to = 1.0) progress: Float, | ||
modifier: Modifier = Modifier, | ||
color: Color = Color.White, | ||
backgroundColor: Color = color.copy(alpha = IndicatorBackgroundOpacity), | ||
numberOfSegments: Int, | ||
) { | ||
Canvas( | ||
modifier | ||
.progressSemantics(progress) | ||
.fillMaxWidth() | ||
.height(SegmentHeight) | ||
.focusable() | ||
) { | ||
drawSegmentsBackground(backgroundColor, numberOfSegments) | ||
drawSegments(progress, color, numberOfSegments) | ||
} | ||
} | ||
|
||
private fun DrawScope.drawSegmentsBackground( | ||
color: Color, | ||
numberOfSegments: Int, | ||
) = drawSegments(1f, color, numberOfSegments) | ||
|
||
private fun DrawScope.drawSegments( | ||
endFraction: Float, | ||
color: Color, | ||
numberOfSegments: Int, | ||
) { | ||
val width = size.width | ||
val height = size.height | ||
// Start drawing from the vertical center of the stroke | ||
val yOffset = height / 2 | ||
|
||
val barEnd = endFraction * width | ||
|
||
val segmentWidth = calculateSegmentWidth(numberOfSegments) | ||
val segmentAndGapWidth = segmentWidth + GapWidth.toPx() | ||
|
||
repeat(numberOfSegments) { index -> | ||
val xOffsetStart = index * segmentAndGapWidth | ||
val shouldDrawLine = xOffsetStart < barEnd | ||
if (shouldDrawLine) { | ||
val xOffsetEnd = (xOffsetStart + segmentWidth).coerceAtMost(barEnd) | ||
// Progress line | ||
drawLine(color, Offset(xOffsetStart, yOffset), Offset(xOffsetEnd, yOffset), StrokeWidth.toPx()) | ||
} | ||
} | ||
} | ||
|
||
private fun DrawScope.calculateSegmentWidth( | ||
numberOfSegments: Int, | ||
): Float { | ||
val width = size.width | ||
val gapsWidth = (numberOfSegments - 1) * GapWidth.toPx() | ||
return (width - gapsWidth) / numberOfSegments | ||
} |
44 changes: 44 additions & 0 deletions
44
...tures/endofyear/src/main/java/au/com/shiftyjelly/pocketcasts/endofyear/StoriesFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package au.com.shiftyjelly.pocketcasts.endofyear | ||
|
||
import android.graphics.Color | ||
import android.os.Bundle | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import androidx.compose.ui.platform.ComposeView | ||
import androidx.compose.ui.platform.ViewCompositionStrategy | ||
import au.com.shiftyjelly.pocketcasts.compose.AppTheme | ||
import au.com.shiftyjelly.pocketcasts.ui.R | ||
import au.com.shiftyjelly.pocketcasts.ui.helper.StatusBarColor | ||
import au.com.shiftyjelly.pocketcasts.views.fragments.BaseDialogFragment | ||
|
||
class StoriesFragment : BaseDialogFragment() { | ||
override val statusBarColor: StatusBarColor | ||
get() = StatusBarColor.Custom(Color.BLACK, true) | ||
|
||
override fun onCreate(savedInstance: Bundle?) { | ||
super.onCreate(savedInstance) | ||
setStyle(STYLE_NORMAL, R.style.BottomSheetDialogThemeBlack) | ||
} | ||
|
||
override fun onCreateView( | ||
inflater: LayoutInflater, | ||
container: ViewGroup?, | ||
savedInstanceState: Bundle?, | ||
): View { | ||
return ComposeView(requireContext()).apply { | ||
setContent { | ||
AppTheme(theme.activeTheme) { | ||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) | ||
StoriesScreen( | ||
onCloseClicked = { dismiss() }, | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
companion object { | ||
fun newInstance() = StoriesFragment() | ||
} | ||
} |
141 changes: 141 additions & 0 deletions
141
...eatures/endofyear/src/main/java/au/com/shiftyjelly/pocketcasts/endofyear/StoriesScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package au.com.shiftyjelly.pocketcasts.endofyear | ||
|
||
import androidx.compose.animation.core.LinearEasing | ||
import androidx.compose.animation.core.animateFloatAsState | ||
import androidx.compose.animation.core.tween | ||
import androidx.compose.foundation.BorderStroke | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Box | ||
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.padding | ||
import androidx.compose.foundation.shape.RoundedCornerShape | ||
import androidx.compose.material.ButtonDefaults | ||
import androidx.compose.material.Icon | ||
import androidx.compose.material.IconButton | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.filled.Share | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.LaunchedEffect | ||
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.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.bars.NavigationButton | ||
import au.com.shiftyjelly.pocketcasts.compose.buttons.RowOutlinedButton | ||
import au.com.shiftyjelly.pocketcasts.compose.preview.ThemePreviewParameterProvider | ||
import au.com.shiftyjelly.pocketcasts.ui.theme.Theme | ||
import au.com.shiftyjelly.pocketcasts.localization.R as LR | ||
|
||
private const val ProgressDurationMs = 5_000 | ||
private val ShareButtonStrokeWidth = 2.dp | ||
private val StoryViewCornerSize = 10.dp | ||
private const val NumberOfSegments = 2 | ||
|
||
@Composable | ||
fun StoriesScreen( | ||
onCloseClicked: () -> Unit, | ||
modifier: Modifier = Modifier, | ||
) { | ||
var running by remember { mutableStateOf(false) } | ||
val progress: Float by animateFloatAsState( | ||
if (running) 1f else 0f, | ||
animationSpec = tween( | ||
durationMillis = ProgressDurationMs, | ||
easing = LinearEasing | ||
) | ||
) | ||
Box(modifier = modifier.background(color = Color.Black)) { | ||
StoryView(color = Color.Gray) | ||
SegmentedProgressIndicator( | ||
progress = progress, | ||
numberOfSegments = NumberOfSegments, | ||
modifier = modifier | ||
.padding(8.dp) | ||
.fillMaxWidth(), | ||
) | ||
CloseButtonView(onCloseClicked) | ||
} | ||
|
||
LaunchedEffect(Unit) { | ||
running = true | ||
} | ||
} | ||
|
||
@Composable | ||
private fun StoryView( | ||
color: Color, | ||
modifier: Modifier = Modifier, | ||
) { | ||
Column { | ||
Box( | ||
modifier = modifier | ||
.fillMaxSize() | ||
.weight(weight = 1f, fill = true) | ||
.clip(RoundedCornerShape(StoryViewCornerSize)) | ||
.background(color = color) | ||
) {} | ||
ShareButton() | ||
} | ||
} | ||
|
||
@Composable | ||
private fun ShareButton() { | ||
RowOutlinedButton( | ||
text = stringResource(id = LR.string.share), | ||
border = BorderStroke(ShareButtonStrokeWidth, Color.White), | ||
colors = ButtonDefaults | ||
.outlinedButtonColors( | ||
backgroundColor = Color.Transparent, | ||
contentColor = Color.White, | ||
), | ||
iconImage = Icons.Default.Share, | ||
onClick = {} | ||
) | ||
} | ||
|
||
@Composable | ||
private fun CloseButtonView( | ||
onCloseClicked: () -> Unit, | ||
modifier: Modifier = Modifier, | ||
) { | ||
Row( | ||
modifier = modifier | ||
.fillMaxWidth() | ||
.padding(top = 16.dp), | ||
horizontalArrangement = Arrangement.End | ||
) { | ||
IconButton( | ||
onClick = onCloseClicked | ||
) { | ||
Icon( | ||
imageVector = NavigationButton.Close.image, | ||
contentDescription = stringResource(NavigationButton.Close.contentDescription), | ||
tint = Color.White | ||
) | ||
} | ||
} | ||
} | ||
|
||
@Preview(showBackground = true) | ||
@Composable | ||
private fun StoriesScreenPreview( | ||
@PreviewParameter(ThemePreviewParameterProvider::class) themeType: Theme.ThemeType, | ||
) { | ||
AppTheme(themeType) { | ||
StoriesScreen( | ||
onCloseClicked = {} | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.