Skip to content
Open
Show file tree
Hide file tree
Changes from 116 commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
8d2040b
YiR: Pre-design scaffolding
cooltey Sep 19, 2025
0916538
Merge branch 'main' into yir-re-design
cooltey Sep 19, 2025
350cf1b
Wire up API calls and put TODOs
cooltey Sep 19, 2025
f0557c0
Put async for api calls
cooltey Sep 19, 2025
6f2b7fb
Merge branch 'main' into yir-re-design
cooltey Sep 22, 2025
42f85eb
Format for the headline/body text
cooltey Sep 23, 2025
e385bb0
Revert "Format for the headline/body text"
cooltey Sep 23, 2025
84b73de
Separate initial screen out
cooltey Sep 23, 2025
26655a5
Onboarding
cooltey Sep 24, 2025
344f904
Simplify a bit
cooltey Sep 24, 2025
43700b5
Initial thought about indivial screens
cooltey Sep 24, 2025
9d93c41
Merge branch 'main' into yir-re-design
cooltey Sep 24, 2025
cdb2548
Add temporary functions for slides
cooltey Sep 24, 2025
9cbbf1f
Review comment
cooltey Sep 24, 2025
259209c
clean up async
cooltey Sep 24, 2025
d7237fc
Fix error
cooltey Sep 24, 2025
7595e56
Consolidate routes
cooltey Sep 25, 2025
65409d7
Update a bit
cooltey Sep 25, 2025
ce28f83
Merge branch 'main' into yir-re-design
cooltey Sep 25, 2025
d4c4592
Remove survey for now and refine the finish action for onboarding and
cooltey Sep 25, 2025
18256af
Fix preview
cooltey Sep 25, 2025
1aff666
YiR: update entry point in More menu. (#5964)
dbrant Sep 25, 2025
f8c7114
YiR: Login dialog in the onboarding screen. (#5965)
dbrant Sep 25, 2025
711a974
Model class
cooltey Sep 25, 2025
1379200
use data class
cooltey Sep 25, 2025
095c7b5
Merge branch 'main' into yir-re-design
cooltey Sep 25, 2025
785e946
Create dataModel for YiR
cooltey Sep 25, 2025
20f226a
Update model
cooltey Sep 25, 2025
3fec482
Update model class and add todos
cooltey Sep 25, 2025
b2a8abb
Update query for top visited articles
cooltey Sep 25, 2025
d8d3cd2
No longer use CenterAlignedTopAppBar with W icon.
dbrant Sep 26, 2025
4266944
Merge branch 'main' into yir-re-design
cooltey Sep 29, 2025
3529736
Wire up onboarding screen to PageActivity, with result.
dbrant Sep 29, 2025
c1fa000
Merge branch 'yir-re-design' of github.com:wikimedia/apps-android-wik…
dbrant Sep 29, 2025
246b99e
Update naming and fix lint
cooltey Sep 29, 2025
45e73cf
Add two parameters for YearInReviewSlides
cooltey Sep 30, 2025
a129b12
Clean up outdated strings
cooltey Sep 30, 2025
e898995
Add filterNotNull() for slide routes
cooltey Sep 30, 2025
1f121e1
Fix translation test
cooltey Oct 1, 2025
a3ee3a7
YiR: save YiR model data to preference (#5967)
cooltey Oct 1, 2025
1e43871
YiR: Create Most visited Categories slide (#5968)
cooltey Oct 1, 2025
b16c57d
YiR: Create Your Top Articles slide (#5969)
cooltey Oct 1, 2025
8be18fc
Merge branch 'main' into yir-re-design
cooltey Oct 2, 2025
cf67139
Fix translation
cooltey Oct 2, 2025
ef1576d
YiR: Create Viewed Edits slide (#5970)
cooltey Oct 3, 2025
a323891
YiR: Add English most popular articles slide (#5971)
cooltey Oct 3, 2025
44fcdc6
Merge branch 'main' into yir-re-design
cooltey Oct 3, 2025
ecaa1a8
YiR: Add Setting to enable/disable. (#5978)
dbrant Oct 3, 2025
7988f7e
Remove duplicated preference from developer settings
cooltey Oct 3, 2025
ba82c1e
Swap donate icon with share icon and adjust the UI a bit
cooltey Oct 3, 2025
fa906ef
YiR: Create Articles Saved slide (#5972)
cooltey Oct 6, 2025
884448e
YiR: Update # of articles edited slide (#5979)
cooltey Oct 6, 2025
e6d7e04
Merge branch 'main' into yir-re-design
cooltey Oct 7, 2025
d34b05e
Fix translation
cooltey Oct 7, 2025
3adcfd2
Use year constant instead of LocalDate.
dbrant Oct 7, 2025
bba160d
YiR: Custom app icon (#5974)
dbrant Oct 7, 2025
b25e2d4
Merge branch 'main' into yir-re-design
dbrant Oct 8, 2025
f74b97c
Tweak verbiage per design.
dbrant Oct 8, 2025
98a77af
YiR: Create Reading Patterns slide (#5982)
cooltey Oct 8, 2025
52f92b4
Use localtime for queries and minor code updates
cooltey Oct 8, 2025
88b444f
Update MW info links.
dbrant Oct 8, 2025
850b6b3
Rename string items a bit
cooltey Oct 8, 2025
2bbdd56
Merge branch 'main' into yir-re-design
cooltey Oct 9, 2025
df380a6
Merge branch 'main' into yir-re-design
cooltey Oct 9, 2025
322dab9
Merge branch 'main' into yir-re-design
cooltey Oct 10, 2025
350014d
Prioritize categories that have 2+ spaces.
dbrant Oct 10, 2025
1d635a6
Merge branch 'yir-re-design' of github.com:wikimedia/apps-android-wik…
dbrant Oct 10, 2025
12b37d3
Merge branch 'main' into yir-re-design
cooltey Oct 10, 2025
1bf48b6
YiR: Create contributor slides (#5991)
cooltey Oct 14, 2025
dc91e9a
YiR: Update personalized "articles read" slides (#5988)
cooltey Oct 14, 2025
2101cdd
Fully integrate with remote config.
dbrant Oct 14, 2025
5ca7b51
Correct color.
dbrant Oct 14, 2025
c02836b
Merge branch 'main' into yir-re-design
Williamrai Oct 14, 2025
7256c1f
Fetch remote config explicitly.
dbrant Oct 14, 2025
0013a71
Unnecessary intermediate vars.
dbrant Oct 14, 2025
5306a9f
Update onboarding illustration.
dbrant Oct 14, 2025
29078a9
Merge branch 'main' into yir-re-design
cooltey Oct 14, 2025
ee1b161
YiR: add a filter for the top visited articles to show if visited > 1…
cooltey Oct 15, 2025
db3f290
Merge branch 'main' into yir-re-design
Williamrai Oct 15, 2025
65cf748
- replaces navigation left button with close button in app bar (#6003)
Williamrai Oct 15, 2025
56275b2
YiR: update local queries to accept time range to meet the feature re…
cooltey Oct 15, 2025
33ad06c
Wire up data start/end times from remote config.
dbrant Oct 15, 2025
6eacd63
Fix calculation of time spent, and explitit units naming.
dbrant Oct 15, 2025
6985a68
Merge branch 'main' into yir-re-design
dbrant Oct 15, 2025
1dadf5f
- adds ui for highlight slide
Williamrai Oct 15, 2025
d844652
YiR: Wire up actual total enabling/disabling based on configuration. …
dbrant Oct 15, 2025
c3ec1a1
- adds proper data for all cases of highlights screen
Williamrai Oct 16, 2025
a9b0d8e
Update style of Donate button.
dbrant Oct 16, 2025
e373872
Correct divider color.
dbrant Oct 16, 2025
f6603c1
Don't actually need a BottomAppBar.
dbrant Oct 16, 2025
ef9221c
Merge branch 'yir-re-design' of github.com:wikimedia/apps-android-wik…
dbrant Oct 16, 2025
71f3890
Improve naming and thread allowDonate throughout.t
dbrant Oct 16, 2025
08b77c5
Reinstitute rounded corner clipping.
dbrant Oct 16, 2025
0dce3c6
- code fixes and adds editor highlight
Williamrai Oct 16, 2025
3aeaa75
YiR: update app articles viewed times screen
cooltey Oct 16, 2025
be4d996
Merge remote-tracking branch 'origin/yir-re-design' into yir-highlights
Williamrai Oct 16, 2025
72deb14
Merge branch 'main' into yir-re-design
cooltey Oct 16, 2025
0b2e656
- code merge fixes
Williamrai Oct 16, 2025
96c4f22
- ensures bottom bar is drawn above the navigation bar (#6013)
Williamrai Oct 16, 2025
5242376
Merge remote-tracking branch 'origin/yir-re-design' into yir-highlights
Williamrai Oct 16, 2025
f4feeab
- code fixes
Williamrai Oct 16, 2025
f1fedf6
Merge branch 'main' into yir-re-design
dbrant Oct 17, 2025
270f077
Complete integration with isAccessible from remote config.
dbrant Oct 17, 2025
41ebebf
- adds screen capture handler
Williamrai Oct 17, 2025
c503c9b
Merge remote-tracking branch 'origin/yir-re-design' into yir-highlights
Williamrai Oct 17, 2025
b2bf6ab
- code cleanup and fixes
Williamrai Oct 17, 2025
178c2ea
- code cleanup and fixes
Williamrai Oct 20, 2025
d1cfb93
Merge remote-tracking branch 'origin/main' into yir-highlights
Williamrai Oct 20, 2025
d2c385a
- code fixes
Williamrai Oct 20, 2025
a8215ea
- string fixes
Williamrai Oct 20, 2025
9936d68
- code fixes
Williamrai Oct 20, 2025
81438af
Merge remote-tracking branch 'origin/main' into yir-highlights
Williamrai Oct 21, 2025
94f4034
- moving remember scroll state position
Williamrai Oct 21, 2025
df271e7
Merge branch 'scroll-state-fix' into yir-highlights
Williamrai Oct 21, 2025
6a0e0d1
- code fixes
Williamrai Oct 21, 2025
3bcacd1
Merge branch 'main' into yir-highlights
cooltey Oct 21, 2025
31d4769
Merge remote-tracking branch 'origin/main' into yir-highlights
Williamrai Oct 21, 2025
2bab417
- update YearInReviewCaptureHandler to handle geo slide screenshot
Williamrai Oct 22, 2025
6c13943
- code fixes
Williamrai Oct 22, 2025
81bc766
Merge remote-tracking branch 'origin/main' into yir-highlights
Williamrai Oct 22, 2025
22a070c
Merge branch 'main' into yir-highlights
Williamrai Oct 22, 2025
33ab45a
- code fixes
Williamrai Oct 22, 2025
2488229
Merge remote-tracking branch 'origin/yir-highlights' into yir-highlights
Williamrai Oct 22, 2025
ac191ff
Merge branch 'main' into yir-highlights
Williamrai Oct 22, 2025
bf5f5a4
Merge remote-tracking branch 'origin/main' into yir-highlights
Williamrai Oct 22, 2025
8b1107b
- code fixes/merge conflict fix
Williamrai Oct 22, 2025
da48dbc
Merge branch 'main' into yir-highlights
Williamrai Oct 22, 2025
c1c6bd7
Merge branch 'main' into yir-highlights
cooltey Oct 22, 2025
e84a6b1
Merge remote-tracking branch 'origin/main' into yir-highlights
Williamrai Oct 24, 2025
4d67b6b
- merge conflict fix
Williamrai Oct 24, 2025
4d76fcf
Merge branch 'main' into yir-highlights
Williamrai Oct 24, 2025
44449b5
Merge branch 'main' into yir-highlights
Williamrai Oct 24, 2025
a68ef71
- Scale ShareableHighlightsCard height to fill remaining space betwee…
Williamrai Oct 24, 2025
18c5d4c
Merge remote-tracking branch 'origin/yir-highlights' into yir-highlights
Williamrai Oct 24, 2025
43c9704
Merge branch 'main' into yir-highlights
Williamrai Oct 24, 2025
99a8460
Merge branch 'main' into yir-highlights
cooltey Oct 24, 2025
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
3 changes: 2 additions & 1 deletion app/src/main/java/org/wikipedia/util/ShareUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ object ShareUtil {
}

fun shareImage(coroutineScope: CoroutineScope, context: Context, bmp: Bitmap,
imageFileName: String, subject: String, text: String) {
imageFileName: String, subject: String, text: String, onShared: (() -> Unit)? = null) {
coroutineScope.launch(CoroutineExceptionHandler { _, msg ->
displayOnCatchMessage(msg, context)
}) {
Expand All @@ -65,6 +65,7 @@ object ShareUtil {
val chooserIntent = buildImageShareChooserIntent(context, subject, text, uri)
context.startActivity(chooserIntent)
}
onShared?.invoke()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,13 @@ class YearInReviewActivity : BaseActivity() {
onBackButtonClick = {
finish()
},
onNextButtonClick = { pagerState ->
onNextButtonClick = { pagerState, currentSlide ->
coroutineScope.launch {
pagerState.animateScrollToPage(pagerState.currentPage + 1)
}
if (currentSlide is YearInReviewScreenData.HighlightsScreen) {
finish()
}
},
onDonateClick = {
EventPlatformClient.submit(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.wikipedia.yearinreview

import android.graphics.Bitmap
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import org.wikipedia.R
import org.wikipedia.util.ShareUtil

@Composable
fun YearInReviewCaptureHandler(
request: YearInReviewCaptureRequest,
onComplete: () -> Unit
) {
val coroutineScope = rememberCoroutineScope()
val context = LocalContext.current

val shareImageCallback: (Bitmap) -> Unit = { bitmap ->
ShareUtil.shareImage(
coroutineScope = coroutineScope,
context = context,
bmp = bitmap,
imageFileName = "year_in_review",
subject = context.getString(R.string.year_in_review_share_subject),
text = context.getString(R.string.year_in_review_share_url),
onShared = onComplete
)
}

when (request) {
is YearInReviewCaptureRequest.StandardScreen -> {
CreateScreenShotBitmap(
screenContent = request.screenData,
onBitmapReady = shareImageCallback
)
}
is YearInReviewCaptureRequest.HighlightsScreen -> {
ShareHighlightsScreenCapture(
highlights = request.highlights,
onBitmapReady = shareImageCallback
)
}
}
}

sealed class YearInReviewCaptureRequest {
data class StandardScreen(val screenData: YearInReviewScreenData) : YearInReviewCaptureRequest()
data class HighlightsScreen(val highlights: List<YearInReviewScreenData.HighlightItem>) : YearInReviewCaptureRequest()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
package org.wikipedia.yearinreview

import android.graphics.Bitmap
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
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.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.fastForEachIndexed
import org.wikipedia.R
import org.wikipedia.compose.ComposeColors
import org.wikipedia.compose.theme.BaseTheme
import org.wikipedia.compose.theme.WikipediaTheme
import org.wikipedia.theme.Theme

@Composable
fun YearInReviewHighlightsScreen(
modifier: Modifier = Modifier,
screenData: YearInReviewScreenData.HighlightsScreen,
onShareHighlights: () -> Unit
) {
Column(
modifier = modifier
) {
Text(
modifier = Modifier
.padding(top = 60.dp, bottom = 16.dp),
text = buildAnnotatedString {
append(stringResource(R.string.year_in_review_highlights_thank_you_message))
withStyle(
style = SpanStyle(
fontWeight = FontWeight.Normal,
)
) {
append(" ")
append(stringResource(R.string.year_in_review_highlights_looking_forward_message))
}
},
color = WikipediaTheme.colors.paperColor,
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center,
fontWeight = FontWeight.Medium
)

ShareableHighlightsCard(
modifier = Modifier
.fillMaxWidth()
.height(324.dp)
.background(ComposeColors.Gray100)
.border(width = 1.dp, color = ComposeColors.Gray300)
.padding(8.dp)
.verticalScroll(rememberScrollState()),
highlights = screenData.highlights,
logoDescription = "Wikipedia logo"
)

Button(
modifier = Modifier
.fillMaxWidth()
.padding(top = 32.dp),
colors = ButtonDefaults.buttonColors(
containerColor = WikipediaTheme.colors.progressiveColor
),
onClick = onShareHighlights
) {
Text(
"Share highlights"
)
}
}
}

@Composable
fun ShareableHighlightsCard(
modifier: Modifier = Modifier,
hashtag: String = "#WikipediaYearinReview",
logoResource: Int = R.drawable.w_nav_mark,
logoDescription: String = "",
highlights: List<YearInReviewScreenData.HighlightItem>,
) {
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = hashtag,
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
lineHeight = 21.sp,
color = ComposeColors.Gray700
)
Image(
modifier = Modifier
.size(163.dp)
.padding(vertical = 4.dp),
painter = painterResource(logoResource),
contentDescription = logoDescription
)
Text(
modifier = Modifier
.padding(4.dp),
text = logoDescription,
fontSize = 12.sp,
lineHeight = 16.sp,
color = ComposeColors.Gray700
)
highlights.forEach { highlightItem ->
HighlightsContent(
modifier = Modifier
.padding(top = 12.dp),
highlightItem = highlightItem
)
}
}
}

@Composable
fun HighlightsContent(
modifier: Modifier = Modifier,
highlightItem: YearInReviewScreenData.HighlightItem
) {
Row(
modifier = modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
modifier = Modifier
.width(98.dp),
text = highlightItem.title,
fontWeight = FontWeight.Bold,
fontSize = 14.sp,
lineHeight = 21.sp
)

if (highlightItem.singleValue != null) {
Text(
text = highlightItem.singleValue,
fontSize = 14.sp,
lineHeight = 21.sp,
color = Color.Black
)
} else {
Column {
highlightItem.items.fastForEachIndexed { index, item ->
Text(
text = buildAnnotatedString {
append("${index + 1}. ")
withStyle(
style = SpanStyle(
color = highlightItem.highlightColor
)
) {
append(text = item)
}
},
lineHeight = 21.sp
)
}
}
}
}
}

@Composable
fun ShareHighlightsScreenCapture(
highlights: List<YearInReviewScreenData.HighlightItem>,
onBitmapReady: (Bitmap) -> Unit
) {
val graphicsLayer = rememberGraphicsLayer()
var isReadyToCapture by remember { mutableStateOf(false) }

if (isReadyToCapture) {
LaunchedEffect(Unit) {
val bitmap = graphicsLayer.toImageBitmap()
onBitmapReady(bitmap.asAndroidBitmap())
}
}

Box(
modifier = Modifier
.fillMaxSize()
.onGloballyPositioned {
isReadyToCapture = true
}
.drawWithContent {
graphicsLayer.record {
drawRect(
color = ComposeColors.White
)
[email protected]()
}
}
.background(ComposeColors.White),
) {
ShareableHighlightsCard(
modifier = Modifier
.align(Alignment.Center)
.padding(horizontal = 34.dp)
.background(ComposeColors.Gray100)
.border(width = 1.dp, color = ComposeColors.Gray300)
.padding(8.dp),
highlights = highlights
)

Text(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 16.dp),
text = stringResource(R.string.year_in_highlights_screenshot_url),
style = MaterialTheme.typography.bodyLarge
)
}
}

@Preview(device = Devices.PIXEL_9)
@Composable
private fun YearInReviewHighlightsScreenPreview() {
BaseTheme(
currentTheme = Theme.LIGHT
) {
YearInReviewHighlightsScreen(
screenData = YearInReviewScreenData.HighlightsScreen(
highlights = listOf(
YearInReviewScreenData.HighlightItem(
title = "Articles I read the longest",
items = listOf(
"Pamela Anderson",
"Pamukkale",
"History of US science fiction and fantasy magazines to 1950"
),
highlightColor = ComposeColors.Blue600
)
)
),
onShareHighlights = {}
)
}
}

@Preview
@Composable
private fun ListItemsPreview() {
BaseTheme(
currentTheme = Theme.LIGHT
) {
HighlightsContent(
highlightItem = YearInReviewScreenData.HighlightItem(
title = "Articles I read the longest",
items = listOf(
"Pamela Anderson",
"Pamukkale",
"History of US science fiction and fantasy magazines to 1950"
),
highlightColor = ComposeColors.Blue600
)
)
}
}

@Preview
@Composable
private fun SingleValuePreview() {
BaseTheme(
currentTheme = Theme.LIGHT
) {
HighlightsContent(
highlightItem = YearInReviewScreenData.HighlightItem(
title = "Minutes read",
singleValue = "924",
highlightColor = ComposeColors.Blue600
)
)
}
}
Loading
Loading