[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-140.17.0esr-15.0-1] [android] Bug 45217: Implement YEC 2026 Takeover for Android Stable



Title: GitLab

Dan Ballard pushed to branch tor-browser-140.17.0esr-15.0-1 at The Tor Project / Applications / Tor Browser

Commits:

  • b9ce1488
    by clairehurst at 2026-09-28T08:43:52-07:00
    [android] Bug 45217: Implement YEC 2026 Takeover for Android Stable
    

10 changed files:

Changes:

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
    ... ... @@ -164,6 +164,9 @@ import org.mozilla.fenix.components.toolbar.ToolbarPosition
    164 164
     import org.mozilla.fenix.tor.TorHomePage
    
    165 165
     import org.mozilla.fenix.tor.UrlQuickLoadViewModel
    
    166 166
     
    
    167
    +import org.mozilla.fenix.tor.TorCampaignViewModel
    
    168
    +import java.util.Locale
    
    169
    +
    
    167 170
     @Suppress("TooManyFunctions", "LargeClass")
    
    168 171
     class HomeFragment : Fragment(), UserInteractionHandler {
    
    169 172
         private val args by navArgs<HomeFragmentArgs>()
    
    ... ... @@ -179,6 +182,7 @@ class HomeFragment : Fragment(), UserInteractionHandler {
    179 182
     
    
    180 183
         private val homeViewModel: HomeScreenViewModel by activityViewModels()
    
    181 184
         private val urlQuickLoadViewModel: UrlQuickLoadViewModel by activityViewModels()
    
    185
    +    private val torCampaignViewModel: TorCampaignViewModel by activityViewModels()
    
    182 186
     
    
    183 187
         private var _bottomToolbarContainerView: BottomToolbarContainerView? = null
    
    184 188
         private val bottomToolbarContainerView: BottomToolbarContainerView
    
    ... ... @@ -973,9 +977,23 @@ class HomeFragment : Fragment(), UserInteractionHandler {
    973 977
             binding.torHomepageView.apply {
    
    974 978
                 setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
    
    975 979
                 setContent {
    
    976
    -                TorHomePage(
    
    977
    -                    toolBarAtTop = settings().toolbarPosition == ToolbarPosition.TOP
    
    978
    -                )
    
    980
    +                FirefoxTheme {
    
    981
    +                    val isToolbarAtTop = components.settings.toolbarPosition == ToolbarPosition.TOP
    
    982
    +                        TorHomePage(
    
    983
    +                            toolBarAtTop = isToolbarAtTop,
    
    984
    +                            shouldInitiallyShowPromo = torCampaignViewModel.shouldInitiallyShowPromo,
    
    985
    +                            onClicked = {
    
    986
    +                                val locale = Locale.getDefault().getLanguage()
    
    987
    +                                var url = "https://www.torproject.org/donate/yec2026-tor-browser-android-${locale}"
    
    988
    +                                (requireActivity() as HomeActivity).openToBrowserAndLoad(
    
    989
    +                                    // from https://gitlab.torproject.org/tpo/applications/tor-browser/-/work_items/45217#note_3464207
    
    990
    +                                    url,
    
    991
    +                                    newTab = true,
    
    992
    +                                    from = BrowserDirection.FromHome,
    
    993
    +                                )
    
    994
    +                            },
    
    995
    +                        )
    
    996
    +                }
    
    979 997
                 }
    
    980 998
             }
    
    981 999
         }
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/CampaignCompose.kt
    1
    +package org.mozilla.fenix.tor
    
    2
    +
    
    3
    +import androidx.annotation.DrawableRes
    
    4
    +import androidx.compose.foundation.Image
    
    5
    +import androidx.compose.foundation.background
    
    6
    +import androidx.compose.foundation.layout.Arrangement
    
    7
    +import androidx.compose.foundation.layout.Box
    
    8
    +import androidx.compose.foundation.layout.BoxWithConstraints
    
    9
    +import androidx.compose.foundation.layout.Column
    
    10
    +import androidx.compose.foundation.layout.PaddingValues
    
    11
    +import androidx.compose.foundation.layout.Row
    
    12
    +import androidx.compose.foundation.layout.Spacer
    
    13
    +import androidx.compose.foundation.layout.fillMaxHeight
    
    14
    +import androidx.compose.foundation.layout.fillMaxWidth
    
    15
    +import androidx.compose.foundation.layout.padding
    
    16
    +import androidx.compose.foundation.layout.size
    
    17
    +import androidx.compose.foundation.layout.wrapContentHeight
    
    18
    +import androidx.compose.foundation.shape.RoundedCornerShape
    
    19
    +import androidx.compose.material.Button
    
    20
    +import androidx.compose.material.ButtonDefaults
    
    21
    +import androidx.compose.material.Icon
    
    22
    +import androidx.compose.material.IconButton
    
    23
    +import androidx.compose.material.Text
    
    24
    +import androidx.compose.runtime.Composable
    
    25
    +import androidx.compose.runtime.MutableState
    
    26
    +import androidx.compose.runtime.mutableStateOf
    
    27
    +import androidx.compose.ui.Alignment
    
    28
    +import androidx.compose.ui.Modifier
    
    29
    +import androidx.compose.ui.res.colorResource
    
    30
    +import androidx.compose.ui.res.painterResource
    
    31
    +import androidx.compose.ui.res.stringResource
    
    32
    +import androidx.compose.ui.text.AnnotatedString
    
    33
    +import androidx.compose.ui.text.TextStyle
    
    34
    +import androidx.compose.ui.text.font.FontFamily
    
    35
    +import androidx.compose.ui.text.font.FontWeight
    
    36
    +import androidx.compose.ui.text.fromHtml
    
    37
    +import androidx.compose.ui.text.style.TextAlign
    
    38
    +import androidx.compose.ui.tooling.preview.Preview
    
    39
    +import androidx.compose.ui.unit.Dp
    
    40
    +import androidx.compose.ui.unit.dp
    
    41
    +import androidx.compose.ui.unit.sp
    
    42
    +import mozilla.components.ui.colors.PhotonColors
    
    43
    +import org.mozilla.fenix.R
    
    44
    +
    
    45
    +
    
    46
    +private val alternateLayoutThreshHold = 500.dp
    
    47
    +
    
    48
    +@Composable
    
    49
    +@CampaignComposePreview
    
    50
    +fun CampaignBox(
    
    51
    +    shouldShowPromo: MutableState<Boolean> = mutableStateOf(true),
    
    52
    +    onDonateButtonClicked: () -> Unit = {},
    
    53
    +    ) {
    
    54
    +    BoxWithConstraints(
    
    55
    +        contentAlignment = Alignment.Center,
    
    56
    +        modifier = Modifier
    
    57
    +            .fillMaxWidth()
    
    58
    +            .fillMaxHeight(),
    
    59
    +    ) {
    
    60
    +        val alternateLayout = this.maxWidth >= alternateLayoutThreshHold
    
    61
    +
    
    62
    +        CampaignLayout(
    
    63
    +            alternateLayout,
    
    64
    +            maxWidth = this.maxWidth,
    
    65
    +            shouldShowPromo,
    
    66
    +            onDonateButtonClicked = onDonateButtonClicked,
    
    67
    +        )
    
    68
    +    }
    
    69
    +}
    
    70
    +
    
    71
    +@Composable
    
    72
    +private fun CampaignLayout(
    
    73
    +    alternateLayout: Boolean,
    
    74
    +    maxWidth: Dp,
    
    75
    +    shouldShowPromo: MutableState<Boolean>,
    
    76
    +    onDonateButtonClicked: () -> Unit,
    
    77
    +) {
    
    78
    +    Column(
    
    79
    +        modifier = Modifier
    
    80
    +            .fillMaxWidth(getVariableWidth(maxWidth))
    
    81
    +            .wrapContentHeight(),
    
    82
    +        horizontalAlignment = Alignment.CenterHorizontally,
    
    83
    +    ) {
    
    84
    +        PurpleBox(
    
    85
    +            alternateLayout,
    
    86
    +            shouldShowPromo,
    
    87
    +            onDonateButtonClicked = onDonateButtonClicked,
    
    88
    +        )
    
    89
    +        Spacer(Modifier.size(8.dp))
    
    90
    +        Text(
    
    91
    +            text = stringResource(R.string.no_donation_required_yec),
    
    92
    +            style = TextStyle(
    
    93
    +                fontSize = 12.5.sp,
    
    94
    +                lineHeight = 18.75.sp,
    
    95
    +                fontFamily = FontFamily.SansSerif,
    
    96
    +                fontWeight = FontWeight(400),
    
    97
    +                color = PhotonColors.LightGrey05,
    
    98
    +                textAlign = TextAlign.Center,
    
    99
    +            ),
    
    100
    +        )
    
    101
    +    }
    
    102
    +}
    
    103
    +
    
    104
    +private fun getVariableWidth(width: Dp): Float =
    
    105
    +    (alternateLayoutThreshHold / width).coerceIn(0.80f, 1.0f)
    
    106
    +
    
    107
    +@Composable
    
    108
    +private fun PurpleBox(
    
    109
    +    alternateLayout: Boolean,
    
    110
    +    shouldShowPromo: MutableState<Boolean>,
    
    111
    +    onDonateButtonClicked: () -> Unit,
    
    112
    +) {
    
    113
    +    Box(
    
    114
    +        modifier = Modifier.background(
    
    115
    +            colorResource(mozilla.components.ui.colors.R.color.photonViolet90),
    
    116
    +            shape = RoundedCornerShape(8.dp),
    
    117
    +        ),
    
    118
    +    ) {
    
    119
    +        Row(
    
    120
    +            modifier = Modifier
    
    121
    +                .fillMaxWidth()
    
    122
    +                .wrapContentHeight(),
    
    123
    +            horizontalArrangement = Arrangement.End,
    
    124
    +        ) {
    
    125
    +            ExitIcon(shouldShowPromo)
    
    126
    +        }
    
    127
    +        DynamicCampaignContent(
    
    128
    +            alternateLayout, onDonateButtonClicked = onDonateButtonClicked,
    
    129
    +        )
    
    130
    +    }
    
    131
    +}
    
    132
    +
    
    133
    +@Composable
    
    134
    +private fun ExitIcon(shouldShowYec: MutableState<Boolean>) {
    
    135
    +    IconButton(
    
    136
    +        onClick = {
    
    137
    +            shouldShowYec.value = false
    
    138
    +        },
    
    139
    +    ) {
    
    140
    +        Icon(
    
    141
    +            painter = painterResource(id = mozilla.components.ui.icons.R.drawable.mozac_ic_cross_20),
    
    142
    +            tint = PhotonColors.White,
    
    143
    +            contentDescription = stringResource(R.string.close_yec_button_description),
    
    144
    +        )
    
    145
    +    }
    
    146
    +}
    
    147
    +
    
    148
    +
    
    149
    +@Composable
    
    150
    +private fun DynamicCampaignContent(
    
    151
    +    alternateLayout: Boolean,
    
    152
    +    onDonateButtonClicked: () -> Unit,
    
    153
    +) {
    
    154
    +    @Composable
    
    155
    +    fun Icon(shouldShow: Boolean, @DrawableRes drawable: Int, contentDescription: String? = null) {
    
    156
    +        if (shouldShow) {
    
    157
    +            Image(
    
    158
    +                painterResource(drawable),
    
    159
    +                contentDescription = contentDescription,
    
    160
    +                alignment = Alignment.Center,
    
    161
    +            )
    
    162
    +        }
    
    163
    +    }
    
    164
    +    Row(
    
    165
    +        modifier = Modifier
    
    166
    +            .padding(start = 16.dp, top = if (alternateLayout) 24.dp else 32.dp, end = 16.dp, bottom = 24.dp)
    
    167
    +            .fillMaxWidth(),
    
    168
    +        verticalAlignment = Alignment.CenterVertically,
    
    169
    +    ) {
    
    170
    +        Column(
    
    171
    +            modifier = Modifier.fillMaxWidth(),
    
    172
    +            horizontalAlignment = if (alternateLayout) Alignment.Start else Alignment.CenterHorizontally,
    
    173
    +        ) {
    
    174
    +            Icon(shouldShow = !alternateLayout, R.drawable.bulb_illo_yec, contentDescription = stringResource(R.string.bulb_illo_yec_description))
    
    175
    +            Spacer(Modifier.size (if (alternateLayout) 0.dp else 16.dp))
    
    176
    +            Row(verticalAlignment = Alignment.CenterVertically) {
    
    177
    +                Icon(shouldShow = alternateLayout, R.drawable.circled_lighning_yec)
    
    178
    +                Spacer(Modifier.size(if (alternateLayout) 8.dp else 0.dp))
    
    179
    +                TitleText()
    
    180
    +            }
    
    181
    +            Spacer(Modifier.size(8.dp))
    
    182
    +            MainText()
    
    183
    +            Spacer(Modifier.size(if (alternateLayout) 16.dp else 24.dp))
    
    184
    +            Row(
    
    185
    +                horizontalArrangement = if (alternateLayout) Arrangement.Start else Arrangement.Center,
    
    186
    +                modifier = Modifier.fillMaxWidth(),
    
    187
    +            ) {
    
    188
    +                DonateButton(onDonateButtonClicked = onDonateButtonClicked, alternateLayout)
    
    189
    +            }
    
    190
    +        }
    
    191
    +    }
    
    192
    +}
    
    193
    +
    
    194
    +
    
    195
    +@Composable
    
    196
    +private fun TitleText() {
    
    197
    +    Text(
    
    198
    +        text = stringResource(R.string.yec26_tor_powered_by_you),
    
    199
    +        style = TextStyle(
    
    200
    +            fontSize = 24.sp,
    
    201
    +            lineHeight = 32.sp,
    
    202
    +            fontWeight = FontWeight(400),
    
    203
    +            color = PhotonColors.White,
    
    204
    +            textAlign = TextAlign.Center,
    
    205
    +            letterSpacing = 0.18.sp,
    
    206
    +        ),
    
    207
    +    )
    
    208
    +}
    
    209
    +
    
    210
    +
    
    211
    +@Composable
    
    212
    +private fun MainText() {
    
    213
    +    Column {
    
    214
    +        Text(
    
    215
    +            AnnotatedString.fromHtml(
    
    216
    +                // Relevant documentation on HTML markup for android https://developer.android.com/guide/topics/resources/string-resource?utm_source=android-studio-app&utm_medium=app#StylingWithHTML
    
    217
    +                stringResource(
    
    218
    +                    R.string.yec26_call_to_action,
    
    219
    +                ),
    
    220
    +            ), style = TextStyle(
    
    221
    +                fontSize = 14.sp,
    
    222
    +                lineHeight = 20.sp,
    
    223
    +                color = PhotonColors.White,
    
    224
    +                fontWeight = FontWeight(400),
    
    225
    +                letterSpacing = 0.25.sp,
    
    226
    +            )
    
    227
    +        )
    
    228
    +    }
    
    229
    +}
    
    230
    +
    
    231
    +@Composable
    
    232
    +private fun DonateButton(onDonateButtonClicked: () -> Unit, alternateLayout: Boolean) {
    
    233
    +    Button(
    
    234
    +        onClick = onDonateButtonClicked,
    
    235
    +        colors = ButtonDefaults.buttonColors(
    
    236
    +            colorResource(mozilla.components.ui.colors.R.color.photonViolet60),
    
    237
    +        ),
    
    238
    +        shape = RoundedCornerShape(4.dp),
    
    239
    +        contentPadding = PaddingValues(horizontal = 16.dp),
    
    240
    +        modifier = if (alternateLayout) Modifier.fillMaxWidth() else Modifier.fillMaxWidth()
    
    241
    +    ) {
    
    242
    +        Text(
    
    243
    +            text = stringResource(R.string.donate_now_yec),
    
    244
    +            textAlign = TextAlign.Center,
    
    245
    +            fontSize = 16.sp,
    
    246
    +            fontWeight = FontWeight.SemiBold,
    
    247
    +            color = PhotonColors.LightGrey05,
    
    248
    +        )
    
    249
    +        Spacer(
    
    250
    +            Modifier.size(8.dp),
    
    251
    +        )
    
    252
    +        Image(
    
    253
    +            painterResource(R.drawable.heart),
    
    254
    +            contentDescription = null,
    
    255
    +        )
    
    256
    +    }
    
    257
    +}
    
    258
    +
    
    259
    +
    
    260
    +
    
    261
    +@Preview(
    
    262
    +    name = "Small Window",
    
    263
    +    widthDp = 400,
    
    264
    +)
    
    265
    +@Preview(
    
    266
    +    name = "Medium Window",
    
    267
    +    widthDp = 700,
    
    268
    +)
    
    269
    +@Preview(
    
    270
    +    name = "Large Window",
    
    271
    +    widthDp = 1000,
    
    272
    +)
    
    273
    +@Preview(
    
    274
    +    name = "RTL Small Window",
    
    275
    +    locale = "ar",
    
    276
    +    widthDp = 400,
    
    277
    +)
    
    278
    +@Preview(
    
    279
    +    name = "RTL Large Window",
    
    280
    +    locale = "ar",
    
    281
    +    widthDp = 1000
    
    282
    +)
    
    283
    +annotation class CampaignComposePreview

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorCampaignViewModel.kt
    1
    +package org.mozilla.fenix.tor
    
    2
    +
    
    3
    +import android.annotation.SuppressLint
    
    4
    +import android.app.Application
    
    5
    +import android.util.Log
    
    6
    +import androidx.compose.runtime.MutableState
    
    7
    +import androidx.compose.runtime.mutableStateOf
    
    8
    +import androidx.lifecycle.AndroidViewModel
    
    9
    +import java.text.SimpleDateFormat
    
    10
    +import java.util.Date
    
    11
    +
    
    12
    +class TorCampaignViewModel(application: Application) : AndroidViewModel(application) {
    
    13
    +
    
    14
    +    val shouldInitiallyShowPromo: MutableState<Boolean> by lazy {
    
    15
    +        mutableStateOf(shouldInitiallyShowPromo())
    
    16
    +    }
    
    17
    +
    
    18
    +    @SuppressLint("SimpleDateFormat")
    
    19
    +    fun shouldInitiallyShowPromo(): Boolean {
    
    20
    +        val dateFormat = SimpleDateFormat("yyyy-MM-dd-hh-zzz")
    
    21
    +        // From https://gitlab.torproject.org/tpo/applications/tor-browser/-/work_items/45217#note_3462659
    
    22
    +        val startDate = dateFormat.parse("2026-10-13-08-UTC")
    
    23
    +        // From https://gitlab.torproject.org/tpo/applications/tor-browser/-/work_items/45217#note_3463954
    
    24
    +        val endDate =   dateFormat.parse("2027-01-05-00-UTC")
    
    25
    +        val currentDate = Date()
    
    26
    +
    
    27
    +        if (currentDate.before(startDate) || currentDate.after(endDate)) {
    
    28
    +            return false
    
    29
    +        }
    
    30
    +        Log.d(
    
    31
    +            "TorCampaignViewModel",
    
    32
    +            "org.mozilla.fenix.BuildConfig.BUILD_TYPE = ${org.mozilla.fenix.BuildConfig.BUILD_TYPE}"
    
    33
    +        )
    
    34
    +        return (org.mozilla.fenix.BuildConfig.BUILD_TYPE == "release") || (org.mozilla.fenix.BuildConfig.BUILD_TYPE == "debug")
    
    35
    +    }
    
    36
    +
    
    37
    +}

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorHomePage.kt
    ... ... @@ -31,11 +31,28 @@ import androidx.compose.ui.unit.sp
    31 31
     import mozilla.components.compose.base.annotation.FlexibleWindowLightDarkPreview
    
    32 32
     import org.mozilla.fenix.R
    
    33 33
     
    
    34
    +import android.annotation.SuppressLint
    
    35
    +import androidx.compose.foundation.layout.Box
    
    36
    +import androidx.compose.runtime.MutableState
    
    37
    +import androidx.compose.runtime.mutableStateOf
    
    38
    +import androidx.compose.runtime.saveable.rememberSaveable
    
    39
    +import androidx.compose.ui.tooling.preview.Preview
    
    40
    +import androidx.compose.ui.tooling.preview.PreviewParameter
    
    41
    +import androidx.compose.ui.tooling.preview.PreviewParameterProvider
    
    42
    +
    
    34 43
     @Composable
    
    35 44
     @FlexibleWindowLightDarkPreview
    
    36 45
     fun TorHomePage(
    
    37 46
         toolBarAtTop: Boolean = true,
    
    47
    +    shouldInitiallyShowPromo: MutableState<Boolean> = mutableStateOf(true),
    
    48
    +    onClicked: () -> Unit = {},
    
    38 49
     ) {
    
    50
    +    // Will persist across a single session, but not multiple sessions.
    
    51
    +    // Tapping the close button 'X' will hide the promo for the duration of the session
    
    52
    +    val shouldShowPromo = rememberSaveable {
    
    53
    +        shouldInitiallyShowPromo
    
    54
    +    }
    
    55
    +
    
    39 56
         Column(
    
    40 57
             modifier = Modifier
    
    41 58
                 .fillMaxSize()
    
    ... ... @@ -64,7 +81,7 @@ fun TorHomePage(
    64 81
         ) {
    
    65 82
             Spacer(modifier = Modifier.size(17.dp))
    
    66 83
             Row(
    
    67
    -            modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically,
    
    84
    +            modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp), verticalAlignment = Alignment.CenterVertically,
    
    68 85
             ) {
    
    69 86
                 Image(
    
    70 87
                     painter = painterResource(R.drawable.tor_browser_app_icon),
    
    ... ... @@ -82,30 +99,73 @@ fun TorHomePage(
    82 99
                 )
    
    83 100
             }
    
    84 101
             Spacer(Modifier.weight(1f))
    
    85
    -        Text(
    
    86
    -            // Moved from the commit 5bb3cc6b93346dabd8d46677fae7f86a8f8a4fc2
    
    87
    -            // "[android] Modify UI/UX", and the file HomeFragment.
    
    88
    -            // Splits by full stops or commas and puts the parts in different lines.
    
    89
    -            // Ignoring separators at the end of the string, it is expected
    
    90
    -            // that there are at most two parts (e.g. "Explore. Privately.").
    
    91
    -            text = stringResource(R.string.tor_explore_privately).replace(
    
    102
    +        if (shouldShowPromo.value) {
    
    103
    +            CampaignBox(
    
    104
    +                shouldShowPromo,
    
    105
    +                onDonateButtonClicked = onClicked,
    
    106
    +            )
    
    107
    +            Spacer(Modifier.weight(1f))
    
    108
    +        } else {
    
    109
    +            Text(
    
    110
    +                // Moved from the commit 5bb3cc6b93346dabd8d46677fae7f86a8f8a4fc2
    
    111
    +                // "[android] Modify UI/UX", and the file HomeFragment.
    
    112
    +                // Splits by full stops or commas and puts the parts in different lines.
    
    113
    +                // Ignoring separators at the end of the string, it is expected
    
    114
    +                // that there are at most two parts (e.g. "Explore. Privately.").
    
    115
    +                text = stringResource(R.string.tor_explore_privately).replace(
    
    92 116
                         " *([.,。।]) *".toRegex(),
    
    93 117
                         "$1\n",
    
    94 118
                     ).trim(),
    
    95
    -            style = TextStyle(
    
    96
    -                color = Color(color = 0xDEFFFFFF),
    
    97
    -                fontSize = 40.sp,
    
    98
    -                textAlign = TextAlign.Start,
    
    99
    -            ),
    
    100
    -            modifier = Modifier.align(Alignment.CenterHorizontally),
    
    101
    -        )
    
    102
    -        Spacer(Modifier.weight(1f))
    
    103
    -        Image(
    
    104
    -            painter = painterResource(
    
    105
    -                id = R.drawable.ic_onion_pattern,
    
    106
    -            ),
    
    107
    -            contentDescription = null, Modifier.fillMaxWidth(),
    
    108
    -        )
    
    119
    +                style = TextStyle(
    
    120
    +                    color = Color(color = 0xDEFFFFFF),
    
    121
    +                    fontSize = 40.sp,
    
    122
    +                    textAlign = TextAlign.Start,
    
    123
    +                ),
    
    124
    +                modifier = Modifier.align(Alignment.CenterHorizontally),
    
    125
    +            )
    
    126
    +        }
    
    127
    +        if (!shouldShowPromo.value) {
    
    128
    +            Spacer(Modifier.weight(1f))
    
    129
    +            Image(
    
    130
    +                painter = painterResource(
    
    131
    +                    id = R.drawable.ic_onion_pattern,
    
    132
    +                ),
    
    133
    +                contentDescription = null, Modifier.fillMaxWidth(),
    
    134
    +            )
    
    135
    +        }
    
    109 136
         }
    
    110 137
         Spacer(modifier = Modifier.size(17.dp))
    
    111 138
     }
    
    139
    +
    
    140
    +@SuppressLint("UnrememberedMutableState")
    
    141
    +@Composable
    
    142
    +@Preview
    
    143
    +/**
    
    144
    + * Relevant documentation
    
    145
    + * https://developer.android.com/develop/ui/compose/tooling/previews#preview-viewmodel
    
    146
    + */
    
    147
    +private fun TorHomePagePreview(
    
    148
    +    @PreviewParameter(
    
    149
    +        BooleanPreviewParameterProvider::class,
    
    150
    +    ) shouldShowPromo: Boolean,
    
    151
    +) {
    
    152
    +    Box(
    
    153
    +        contentAlignment = Alignment.TopStart,
    
    154
    +        modifier = Modifier.fillMaxSize(),
    
    155
    +    ) {
    
    156
    +        TorHomePage(
    
    157
    +            // restricted vertically so will not follow contentAlignment
    
    158
    +            shouldInitiallyShowPromo = mutableStateOf( shouldShowPromo),
    
    159
    +            toolBarAtTop = true,
    
    160
    +            onClicked = {},
    
    161
    +        )
    
    162
    +    }
    
    163
    +}
    
    164
    +
    
    165
    +private class BooleanPreviewParameterProvider :
    
    166
    +    PreviewParameterProvider<Boolean> {
    
    167
    +    override val values: Sequence<Boolean>
    
    168
    +        get() = sequenceOf(
    
    169
    +            true, false
    
    170
    +        )
    
    171
    +}

  • mobile/android/fenix/app/src/main/res/drawable/bulb_illo_yec.xml
    1
    +<vector xmlns:android="http://schemas.android.com/apk/res/android"
    
    2
    +    android:width="126dp"
    
    3
    +    android:height="184dp"
    
    4
    +    android:viewportWidth="126"
    
    5
    +    android:viewportHeight="184">
    
    6
    +  <path
    
    7
    +      android:pathData="M19.7,73.13a49.65,49.97 0,1 0,99.29 0a49.65,49.97 0,1 0,-99.29 0z"
    
    8
    +      android:fillColor="#6757E0"/>
    
    9
    +  <path
    
    10
    +      android:pathData="M40.23,157.53C40.43,156.58 41.41,156 42.33,156.3C48.3,158.22 54.67,158.51 60.79,157.14L60.96,157.1C62.16,156.83 63.23,157.93 62.92,159.14L57.33,181.27C57.19,181.84 56.81,182.35 56.25,182.62C52.83,184.26 47.81,184.92 37.17,181.35C36.16,181.01 35.57,179.96 35.79,178.92L40.23,157.53Z"
    
    11
    +      android:fillColor="#6757E0"/>
    
    12
    +  <path
    
    13
    +      android:pathData="M59.5,129.87C60.59,125.86 69.88,125.85 74.34,133.26C76.94,138.01 73.23,142.23 71.61,143.59C71.58,143.61 71.64,143.56 71.61,143.59C68.61,146.1 66.44,146.76 64.99,147.52C69.21,146.04 71.55,144.86 75.51,144.25C81.31,143.35 86.38,143.44 88.83,145.39C90.15,146.74 89.52,149 88.08,149.42C86.64,149.84 84.41,149.89 78.07,149.66C75.87,149.58 71.82,149.85 68.45,151.08C71.78,151.05 84.63,152.28 84.66,156.49C84.66,156.94 84.55,157.36 84.33,157.74C84.32,157.76 84.31,157.78 84.3,157.8C84.3,157.8 84.3,157.81 84.29,157.81L84.29,157.82C82.74,160.41 75.29,157.53 72.13,156.58C69.77,155.87 68.25,155.67 65.79,155.5C68.24,155.54 81.63,160.65 79.77,165.86C79.72,166.01 79.65,166.16 79.57,166.3C76.95,169.33 69.97,165.18 62.24,157.93C56.2,159.41 44.97,158.07 41.84,156.51C41.84,156.51 38.37,152.92 36.52,150.21C34.91,147.85 31.45,143.85 30.26,139.9C29.66,137.94 30.24,135.85 31.6,134.32C33.82,131.83 37.88,128.51 42.76,127.02C49.11,125.08 53.43,130.74 46.54,133.67C39.65,136.6 38.34,136.55 39.65,139.68C40.97,142.8 48.77,144.61 52.52,144.37C63.89,144.45 68.84,137.25 65.09,134.97C60.52,133.06 58.91,132.06 59.5,129.87Z"
    
    14
    +      android:fillColor="#EDB6FF"/>
    
    15
    +  <path
    
    16
    +      android:pathData="M42.35,129.44L43.16,132.04C43.35,132.63 43.97,132.98 44.55,132.77C46.43,132.08 48.74,130.71 47.89,128.9C47.04,127.09 44.62,127.47 42.96,128.09C42.42,128.29 42.18,128.89 42.35,129.44Z"
    
    17
    +      android:fillColor="#6757E0"/>
    
    18
    +  <path
    
    19
    +      android:pathData="M67.02,130.68L66.04,132.46C65.77,132.96 65.17,133.19 64.64,132.96C62.86,132.15 60.68,130.7 61.76,129.28C62.79,127.94 65,128.47 66.56,129.17C67.13,129.43 67.32,130.13 67.02,130.68Z"
    
    20
    +      android:fillColor="#6757E0"/>
    
    21
    +  <path
    
    22
    +      android:pathData="M54.16,170.41C53.61,173.97 47.92,176.04 47.68,176.13C47.62,176.15 47.55,176.16 47.48,176.15C47.42,176.13 47.35,176.11 47.3,176.07C47.09,175.91 42.28,172.22 42.82,168.66C42.95,167.83 43.41,167.08 44.08,166.57C44.76,166.07 45.61,165.87 46.44,165.99C47.49,166.15 48.33,166.75 48.79,167.6C49.47,166.92 50.46,166.61 51.5,166.77C52.33,166.9 53.08,167.36 53.58,168.04C54.08,168.72 54.28,169.57 54.16,170.41Z"
    
    23
    +      android:fillColor="#B3E54E"/>
    
    24
    +  <path
    
    25
    +      android:pathData="M68.07,45.9C81.97,45.9 93.25,57.83 93.25,72.54C93.25,82.29 88.3,90.81 80.92,95.46C79.64,96.27 78.76,97.64 78.76,99.16V102.02C78.76,104.23 76.98,106.02 74.78,106.02H61.35C59.15,106.02 57.37,104.23 57.37,102.02V99.16C57.37,97.64 56.49,96.27 55.21,95.46C47.83,90.81 42.88,82.29 42.88,72.54C42.88,57.83 54.16,45.9 68.07,45.9Z"
    
    26
    +      android:fillColor="#EDB6FF"/>
    
    27
    +  <path
    
    28
    +      android:pathData="M79.18,70.66C82.81,70.66 85.75,73.62 85.75,77.27V78.41C85.75,80.47 84.9,82.44 83.41,83.84L76.91,89.95C75.6,91.18 74.86,92.9 74.86,94.69V105.79C74.86,107.61 73.39,109.09 71.58,109.09C69.77,109.09 68.3,107.61 68.3,105.79V94.82C68.3,92.96 67.5,91.18 66.1,89.95L59.22,83.87C57.62,82.46 56.71,80.42 56.71,78.28V77.74C56.71,73.83 59.85,70.66 63.74,70.66C66.02,70.66 68.15,71.77 69.47,73.64L71.58,76.63L73.82,73.44C75.06,71.7 77.05,70.66 79.18,70.66ZM79.18,71.6C77.36,71.6 75.64,72.49 74.59,73.99L72.15,77.44L74.05,80.14C74.59,80.9 74.75,81.88 74.49,82.78C73.63,85.75 69.4,85.75 68.62,82.72C68.39,81.85 68.56,80.91 69.08,80.17L71.01,77.44L68.71,74.19C67.57,72.57 65.71,71.6 63.74,71.6C60.37,71.6 57.64,74.35 57.64,77.74V78.28C57.64,80.15 58.44,81.93 59.84,83.16L66.72,89.24C68.32,90.65 69.23,92.68 69.23,94.82V105.79C69.23,107.09 70.28,108.15 71.58,108.15C72.88,108.15 73.93,107.09 73.93,105.79V94.69C73.93,92.63 74.77,90.67 76.27,89.26L82.77,83.15C84.07,81.93 84.81,80.21 84.81,78.41V77.27C84.81,74.14 82.29,71.6 79.18,71.6ZM69.84,80.72C69.48,81.23 69.37,81.88 69.52,82.49C70.06,84.55 72.99,84.59 73.59,82.51C73.77,81.89 73.66,81.21 73.29,80.68L71.58,78.26L69.84,80.72Z"
    
    29
    +      android:fillColor="#6757E0"
    
    30
    +      android:fillType="evenOdd"/>
    
    31
    +  <path
    
    32
    +      android:pathData="M60.51,52.98V57.88L61.84,56.52L62.42,57.11L61.13,58.42L64.9,58.43L64.9,59.26L61.07,59.25L62.42,60.61L61.84,61.2L60.51,59.85V64.76H59.69V59.89L58.4,61.2L57.82,60.61L59.17,59.24L55.3,59.23L55.3,58.4L59.11,58.41L57.82,57.11L58.4,56.52L59.69,57.84V52.98L60.51,52.98Z"
    
    33
    +      android:fillColor="#6757E0"/>
    
    34
    +  <path
    
    35
    +      android:pathData="M96.16,100.6C96.24,100.48 96.39,100.44 96.52,100.5L109.39,106.96C109.5,107.01 109.56,107.12 109.55,107.23C109.54,107.35 109.46,107.44 109.35,107.48L104.42,108.89L108.95,113.02C109.05,113.11 109.07,113.27 108.99,113.38C108.91,113.5 108.76,113.54 108.64,113.48L97.87,108.07C97.76,108.01 97.7,107.9 97.71,107.79C97.73,107.67 97.81,107.57 97.92,107.54L102.83,106.34L96.22,100.97C96.11,100.88 96.08,100.72 96.16,100.6Z"
    
    36
    +      android:fillColor="#FBF1FE"/>
    
    37
    +  <path
    
    38
    +      android:pathData="M39.02,89.13C39.18,89.05 39.37,89.11 39.47,89.26C39.57,89.41 39.53,89.61 39.39,89.72L30.08,97.26L37.25,98C37.39,98.03 37.5,98.15 37.52,98.3C37.53,98.45 37.46,98.59 37.32,98.66L23.77,105.46C23.61,105.54 23.42,105.49 23.32,105.35C23.22,105.2 23.24,105 23.37,104.88L27.62,100.14L22.87,97.91C22.73,97.87 22.63,97.75 22.62,97.6C22.61,97.46 22.68,97.32 22.81,97.26L39.02,89.13Z"
    
    39
    +      android:fillColor="#FBF1FE"/>
    
    40
    +  <path
    
    41
    +      android:pathData="M123.13,68.64C123.27,68.65 123.4,68.74 123.45,68.88C123.5,69.02 123.45,69.17 123.34,69.26L119.35,73.55L125.75,75.82C125.92,75.87 126.03,76.04 126,76.22C125.96,76.39 125.81,76.52 125.64,76.51L110.49,75.95C110.34,75.94 110.21,75.84 110.17,75.7C110.12,75.56 110.17,75.41 110.29,75.32L115.29,71.37L104.93,68.68C104.76,68.63 104.65,68.46 104.67,68.28C104.7,68.1 104.85,67.97 105.03,67.98L123.13,68.64Z"
    
    42
    +      android:fillColor="#FBF1FE"/>
    
    43
    +  <path
    
    44
    +      android:pathData="M7.86,58.04C8.01,57.84 8.26,57.75 8.5,57.82L38.09,66.06C38.38,66.14 38.57,66.43 38.52,66.74C38.47,67.04 38.2,67.25 37.9,67.24L20.25,66.62L25.86,75.22C26,75.43 26,75.7 25.85,75.9C25.71,76.11 25.45,76.2 25.21,76.13L0.44,69.25C0.15,69.17 -0.03,68.89 0.01,68.59C0.05,68.3 0.3,68.07 0.6,68.07L13.64,68.04L7.83,58.71C7.7,58.51 7.71,58.24 7.86,58.04Z"
    
    45
    +      android:fillColor="#FBF1FE"/>
    
    46
    +  <path
    
    47
    +      android:pathData="M110.83,22.61C111,22.43 111.26,22.37 111.5,22.46C111.73,22.55 111.89,22.77 111.89,23.03L111.88,34.23L123.15,27.18C123.41,27.02 123.75,27.08 123.94,27.31C124.14,27.55 124.13,27.89 123.92,28.11L106.23,47.48C106.06,47.67 105.79,47.73 105.55,47.64C105.32,47.54 105.17,47.3 105.18,47.05L104.25,37.8L90.51,46.68C90.25,46.86 89.91,46.82 89.7,46.59C89.5,46.35 89.5,46 89.71,45.77L110.83,22.61Z"
    
    48
    +      android:fillColor="#FBF1FE"/>
    
    49
    +  <path
    
    50
    +      android:pathData="M36.24,30.56C36.35,30.52 36.47,30.55 36.55,30.64L46.29,41.31C46.38,41.42 46.38,41.58 46.29,41.69C46.2,41.79 46.04,41.81 45.92,41.73L38.95,36.82L39.16,41.9C39.16,42.02 39.09,42.12 38.98,42.17C38.88,42.21 38.75,42.19 38.67,42.1L30.52,33.17C30.42,33.07 30.42,32.91 30.51,32.8C30.6,32.69 30.75,32.67 30.87,32.74L36.07,35.99L36.07,30.83C36.07,30.71 36.14,30.61 36.24,30.56Z"
    
    51
    +      android:fillColor="#FBF1FE"/>
    
    52
    +  <path
    
    53
    +      android:pathData="M83.38,1.04C84.06,0.76 84.56,1.58 84.05,2.11C78.47,8 74.32,14.25 72.02,22.25C71.92,22.6 72.3,22.8 72.52,22.51C74.31,20.1 77.19,15.8 86.33,12.8C86.67,12.69 86.93,13.09 86.7,13.36C79.51,21.75 77.82,24.26 75.49,28.84C74.51,30.77 73.27,35.53 74.85,39.68C75.09,40.3 74.62,41.04 73.95,41C72.53,40.9 70.85,40.81 69.71,40.79C68.46,40.77 67.03,40.69 65.59,40.74C64.86,40.76 64.19,40.3 63.98,39.6C61.22,30.2 61.21,27.1 62.76,20.66C65.24,10.34 76.85,3.68 83.38,1.04Z"
    
    54
    +      android:fillColor="#B3E54E"/>
    
    55
    +  <path
    
    56
    +      android:pathData="M84.89,0.1C85.64,-0.17 86.37,0.14 86.74,0.73C87.11,1.33 87.07,2.14 86.52,2.72C81.98,7.51 78.42,12.51 76.05,18.5C76.35,18.18 76.67,17.86 77.04,17.53C78.98,15.81 82.11,13.93 87.8,11.87L87.82,11.86C89.09,11.45 90.02,12.97 89.19,13.93C82.03,22.3 80.39,24.75 78.11,29.23C77.67,30.09 77.14,31.65 76.92,33.5C76.7,35.35 76.79,37.41 77.51,39.3C77.75,39.93 77.63,40.59 77.3,41.08C76.98,41.56 76.39,41.95 75.67,41.89C74.26,41.79 72.6,41.71 71.49,41.69C70.22,41.67 69.1,41.61 67.83,41.65C66.68,41.69 65.57,40.95 65.28,39.75C63.13,31.02 63.31,24.71 64.54,20.4C66,15.3 69.43,10.9 73.27,7.47C77.12,4.02 81.45,1.48 84.81,0.12L84.89,0.1ZM85.84,2.07C86.35,1.54 85.85,0.72 85.16,1C78.63,3.64 68.22,10.93 65.44,20.66L65.38,20.86C64.26,24.96 64.09,31.03 66.19,39.53C66.37,40.26 67.05,40.73 67.8,40.71C69.1,40.67 70.28,40.73 71.5,40.75C72.63,40.77 74.32,40.86 75.74,40.96C76.38,41 76.85,40.31 76.66,39.7L76.64,39.64C75.05,35.49 76.29,30.73 77.27,28.8C79.61,24.22 81.3,21.71 88.48,13.32C88.71,13.05 88.45,12.65 88.11,12.76C76.85,16.83 76.1,20.06 74.3,22.47C74.08,22.76 73.7,22.56 73.8,22.21C76.07,14.33 80.13,8.15 85.58,2.35L85.84,2.07Z"
    
    57
    +      android:fillColor="#FBF1FE"/>
    
    58
    +  <path
    
    59
    +      android:pathData="M50.16,138.72C51.38,135.7 53.42,135.16 54.35,135.29C56.45,135.77 56.78,138.34 56.65,140.14C56.61,140.68 56.13,141.08 55.59,141.09L55.21,141.1C53.6,141.14 52,140.74 50.62,139.96C50.19,139.71 49.97,139.2 50.16,138.72Z"
    
    60
    +      android:fillColor="#FBF1FE"/>
    
    61
    +  <path
    
    62
    +      android:pathData="M54.26,133.01C54.76,133.02 55.15,133.43 55.15,133.92C55.14,134.42 54.74,134.82 54.24,134.82C53.75,134.81 53.35,134.41 53.36,133.91C53.36,133.41 53.76,133.01 54.26,133.01Z"
    
    63
    +      android:fillColor="#FBF1FE"/>
    
    64
    +  <path
    
    65
    +      android:pathData="M53.4,130.79C53.89,130.79 54.29,131.2 54.29,131.7C54.28,132.19 53.88,132.59 53.38,132.59C52.89,132.59 52.49,132.18 52.49,131.68C52.5,131.18 52.9,130.78 53.4,130.79Z"
    
    66
    +      android:fillColor="#FBF1FE"/>
    
    67
    +  <path
    
    68
    +      android:pathData="M52.76,128.56C53.25,128.56 53.65,128.97 53.65,129.47C53.64,129.97 53.24,130.37 52.74,130.36C52.25,130.36 51.85,129.95 51.85,129.45C51.86,128.95 52.26,128.55 52.76,128.56Z"
    
    69
    +      android:fillColor="#FBF1FE"/>
    
    70
    +  <path
    
    71
    +      android:pathData="M53.44,126.34C53.93,126.35 54.33,126.75 54.33,127.25C54.32,127.75 53.92,128.15 53.42,128.15C52.93,128.14 52.53,127.74 52.54,127.24C52.54,126.74 52.94,126.34 53.44,126.34Z"
    
    72
    +      android:fillColor="#FBF1FE"/>
    
    73
    +  <path
    
    74
    +      android:pathData="M54.78,124.33C55.28,124.34 55.68,124.74 55.67,125.24C55.67,125.74 55.26,126.14 54.77,126.14C54.27,126.13 53.87,125.72 53.88,125.23C53.88,124.73 54.29,124.33 54.78,124.33Z"
    
    75
    +      android:fillColor="#FBF1FE"/>
    
    76
    +  <path
    
    77
    +      android:pathData="M55.91,122.12C56.4,122.12 56.8,122.53 56.8,123.03C56.79,123.53 56.39,123.93 55.89,123.92C55.4,123.92 55,123.51 55,123.01C55.01,122.51 55.41,122.11 55.91,122.12Z"
    
    78
    +      android:fillColor="#FBF1FE"/>
    
    79
    +  <path
    
    80
    +      android:pathData="M56.37,119.9C56.86,119.9 57.26,120.31 57.26,120.81C57.25,121.31 56.85,121.71 56.35,121.71C55.86,121.7 55.46,121.29 55.46,120.79C55.47,120.3 55.87,119.9 56.37,119.9Z"
    
    81
    +      android:fillColor="#FBF1FE"/>
    
    82
    +  <path
    
    83
    +      android:pathData="M55.29,117.67C55.78,117.67 56.18,118.08 56.17,118.58C56.17,119.08 55.77,119.48 55.27,119.47C54.78,119.47 54.38,119.06 54.38,118.57C54.39,118.07 54.79,117.67 55.29,117.67Z"
    
    84
    +      android:fillColor="#FBF1FE"/>
    
    85
    +  <path
    
    86
    +      android:pathData="M53.54,115.64C54.03,115.64 54.43,116.05 54.43,116.55C54.42,117.04 54.02,117.45 53.52,117.44C53.03,117.44 52.63,117.03 52.64,116.53C52.64,116.03 53.04,115.63 53.54,115.64Z"
    
    87
    +      android:fillColor="#FBF1FE"/>
    
    88
    +  <path
    
    89
    +      android:pathData="M70.99,45.9C85.61,45.9 97.46,57.83 97.46,72.54C97.46,82.31 92.25,90.84 84.47,95.48L84.35,95.56C83.09,96.36 82.24,97.71 82.24,99.22V102.02C82.24,103.46 81.47,104.73 80.33,105.44C80.92,105.82 81.3,106.49 81.3,107.24C81.3,108.08 80.82,108.81 80.13,109.17C80.82,109.53 81.3,110.25 81.3,111.09C81.3,111.93 80.82,112.66 80.13,113.02C80.82,113.38 81.3,114.11 81.3,114.94C81.3,116.14 80.34,117.11 79.15,117.11H62.6C61.41,117.11 60.45,116.14 60.45,114.94C60.45,114.11 60.93,113.38 61.63,113.02C60.93,112.66 60.45,111.93 60.45,111.09C60.45,110.25 60.93,109.53 61.63,109.17C60.93,108.81 60.45,108.08 60.45,107.24C60.45,106.44 60.89,105.74 61.54,105.36C60.46,104.65 59.75,103.42 59.75,102.02V99.22C59.75,97.71 58.9,96.36 57.64,95.56L57.52,95.48C49.74,90.84 44.52,82.3 44.52,72.54C44.52,57.83 56.38,45.9 70.99,45.9ZM70.99,46.85C56.89,46.85 45.46,58.35 45.46,72.54C45.46,81.96 50.49,90.19 57.99,94.67C59.56,95.6 60.69,97.28 60.69,99.22V102.02C60.69,103.71 62.05,105.08 63.73,105.08H78.26C79.94,105.08 81.3,103.71 81.3,102.02V99.22C81.3,97.28 82.43,95.6 83.99,94.67C91.5,90.19 96.53,81.96 96.53,72.54C96.53,58.35 85.1,46.85 70.99,46.85Z"
    
    90
    +      android:fillColor="#FBF1FE"
    
    91
    +      android:fillType="evenOdd"/>
    
    92
    +  <path
    
    93
    +      android:pathData="M52.9,113.21C53.4,113.21 53.79,113.62 53.79,114.12C53.79,114.62 53.38,115.02 52.89,115.01C52.39,115.01 51.99,114.6 52,114.1C52,113.6 52.41,113.2 52.9,113.21Z"
    
    94
    +      android:fillColor="#FBF1FE"/>
    
    95
    +  <path
    
    96
    +      android:pathData="M53.14,110.99C53.64,110.99 54.03,111.4 54.03,111.9C54.03,112.4 53.62,112.8 53.13,112.79C52.63,112.79 52.23,112.38 52.24,111.88C52.24,111.38 52.65,110.98 53.14,110.99Z"
    
    97
    +      android:fillColor="#FBF1FE"/>
    
    98
    +  <path
    
    99
    +      android:pathData="M54.71,108.78C55.2,108.78 55.6,109.19 55.6,109.69C55.59,110.19 55.19,110.59 54.69,110.58C54.2,110.58 53.8,110.17 53.8,109.67C53.81,109.17 54.21,108.77 54.71,108.78Z"
    
    100
    +      android:fillColor="#FBF1FE"/>
    
    101
    +  <path
    
    102
    +      android:pathData="M57.04,107.82C57.53,107.82 57.93,108.23 57.93,108.73C57.92,109.23 57.52,109.63 57.02,109.62C56.53,109.62 56.13,109.21 56.13,108.71C56.14,108.21 56.54,107.81 57.04,107.82Z"
    
    103
    +      android:fillColor="#FBF1FE"/>
    
    104
    +  <path
    
    105
    +      android:pathData="M59.3,107.47C59.79,107.48 60.19,107.88 60.19,108.38C60.18,108.88 59.78,109.28 59.28,109.28C58.79,109.27 58.39,108.87 58.39,108.37C58.4,107.87 58.8,107.47 59.3,107.47Z"
    
    106
    +      android:fillColor="#FBF1FE"/>
    
    107
    +</vector>

  • mobile/android/fenix/app/src/main/res/drawable/circled_lighning_yec.xml
    1
    +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="false" android:height="34dp" android:viewportHeight="34" android:viewportWidth="34" android:width="34dp">
    
    2
    +
    
    3
    +    <path android:fillAlpha="0.25" android:fillColor="#000000" android:pathData="M17,0L17,0A17,17 0,0 1,34 17L34,17A17,17 0,0 1,17 34L17,34A17,17 0,0 1,0 17L0,17A17,17 0,0 1,17 0z"/>
    
    4
    +
    
    5
    +    <path android:fillColor="#FFAC33" android:pathData="M24.469,15.825C24.396,15.63 24.209,15.5 24,15.5H17.962L21.445,8.729C21.555,8.516 21.498,8.255 21.309,8.108C21.219,8.035 21.109,8 21,8C20.883,8 20.767,8.041 20.674,8.122L17,11.294L9.674,17.622C9.516,17.758 9.459,17.979 9.532,18.174C9.605,18.369 9.791,18.5 10,18.5H16.038L12.555,25.271C12.446,25.484 12.502,25.744 12.691,25.892C12.781,25.965 12.891,26 13,26C13.116,26 13.233,25.959 13.326,25.878L17,22.706L24.326,16.378C24.485,16.242 24.542,16.021 24.469,15.825Z"/>
    
    6
    +
    
    7
    +</vector>

  • mobile/android/fenix/app/src/main/res/drawable/globe_chain_burst_yec.xml
    1
    +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="124dp" android:viewportHeight="124" android:viewportWidth="160" android:width="160dp">
    
    2
    +      
    
    3
    +    <path android:fillColor="#B6E368" android:pathData="M79.97,86.16C65.19,89.07 56.28,80.34 53.67,75.61L34.02,84.97L55.14,84.24L42.62,106.51L63.16,91.39L61.15,117.92L73.64,93L84.86,111.85L79.98,86.16H79.97Z"/>
    
    4
    +      
    
    5
    +    <path android:fillColor="#B6E368" android:pathData="M72.38,32.02C87.13,28.91 96.16,37.52 98.83,42.21L118.35,32.58L97.24,33.6L109.46,11.17L89.13,26.57L90.78,0L78.63,25.09L67.15,6.4L72.38,32.02Z"/>
    
    6
    +      
    
    7
    +    <path android:fillAlpha="0.8" android:fillColor="#C272FF" android:fillType="evenOdd" android:pathData="M82.86,42.77H84.19V44.18H82.79V42.84H80.14V44.18H81.46V45.52H82.79V48.27H84.19V51.09H82.79V48.34H81.4V45.59H80.06V44.18H78.74V42.84H77.34V53.77H84.19V51.09H85.59V53.77H89.58V55.18H92.31V56.59H89.51V55.18H85.6V67.44H89.58V66.1H92.38V67.44H93.71V68.85H92.38V70.26H91.05V71.67H89.65V73.01H88.25V74.35H86.99V75.76H85.6V74.35H86.86V72.94H88.25V71.6H89.65V70.26H90.98V68.85H92.31V67.51H89.58V68.85H85.6V71.67H84.2V74.42H82.8V75.76H85.6V77.17H81.4V74.35H82.8V71.6H84.19V68.85H77.34V77.17H81.4V78.43H71.88V77.17H67.76V75.76H66.43V74.35H65.1V73.01H63.7V71.67H62.38V70.26H63.78V71.6H65.1V72.94H66.5V74.35H67.83V75.76H70.56V74.42H69.16V71.67H67.83V68.85H63.7V67.51H60.98V68.85H59.58V67.44H58.25V55.18H59.65V67.44H60.98V66.1H63.78V67.44H67.83V55.18H63.78V56.59H60.98V55.18H59.65V52.36H60.98V49.61H62.38V48.27H63.78V46.93H65.1V45.59H66.43V44.18H69.23V45.59H66.5V47H65.17V48.34H63.77V49.68H62.37V52.43H61.04V55.18H63.7V53.77H67.83V51.09H69.22V53.77H75.94V42.84H74.68V44.18H73.28V42.84H70.62V44.18H69.22V42.77H70.55V41.43H82.86V42.77V42.77ZM69.22,71.59H70.55V74.34H71.95V77.16H75.94V68.84H69.23V71.59H69.22ZM77.34,67.44H84.19V55.17H77.34V67.44ZM69.22,67.44H75.94V55.17H69.22V67.44Z" android:strokeAlpha="0.8"/>
    
    8
    +      
    
    9
    +    <path android:fillAlpha="0.8" android:fillColor="#C272FF" android:pathData="M62.37,70.25H60.98V68.84H62.37V70.25Z" android:strokeAlpha="0.8"/>
    
    10
    +      
    
    11
    +    <path android:fillAlpha="0.8" android:fillColor="#C272FF" android:pathData="M95.1,67.44H93.7V55.17H95.1V67.44Z" android:strokeAlpha="0.8"/>
    
    12
    +      
    
    13
    +    <path android:fillAlpha="0.8" android:fillColor="#C272FF" android:pathData="M86.99,45.58H88.25V46.92H89.64V48.26H90.97V49.6H92.37V52.35H93.7V55.17H92.3V52.42H90.97V49.67H89.58V48.33H88.25V46.99H86.85V45.58H84.19V44.17H86.99V45.58V45.58Z" android:strokeAlpha="0.8"/>
    
    14
    +      
    
    15
    +    <path android:fillAlpha="0.8" android:fillColor="#C272FF" android:pathData="M73.28,45.58H71.95V48.33H70.62V51.08H69.22V48.26H70.55V45.51H71.88V44.17H73.28V45.58Z" android:strokeAlpha="0.8"/>
    
    16
    +      
    
    17
    +    <path android:fillAlpha="0.8" android:fillColor="#00000000" android:pathData="M84.19,44.18V42.77H82.86V41.43H70.55V42.77H69.22V44.18M84.19,44.18H82.79V42.84H80.14V44.18H81.46V45.52H82.79V48.27H84.19V51.09M84.19,44.18V45.59H86.85V47H88.25V48.34H89.58V49.68H90.97V52.43H92.3V55.18M84.19,44.18H86.99V45.59H88.25V46.93H89.64V48.27H90.97V49.61H92.37V52.35H93.7V55.17M69.22,44.18H66.43V45.59H65.1V46.93H63.77V48.27H62.37V49.61H60.98V52.35H59.65V55.17M69.22,44.18V45.59H66.5V47H65.17V48.34H63.77V49.68H62.37V52.43H61.04V55.18H63.7V53.77H67.82V51.09H69.22M69.22,44.18H70.62V42.84H73.28V44.18M93.7,55.17H95.1V67.44H93.7M93.7,55.17V67.44M84.19,51.08H82.79V48.33H81.4V45.58H80.06V44.17H78.74V42.84H77.34V53.76H84.19V51.08H84.19ZM84.19,51.08H85.59V53.76H89.58V55.17H92.3M93.7,67.44H92.37V66.1H89.58V67.44H85.59V55.17H89.5V56.58H92.3V55.17H93.7M93.7,67.44V68.85H92.37V70.26H91.04V71.67H89.64V73.01H88.25V74.35H86.99V75.76H85.59M85.59,75.75V74.34H86.85V72.93H88.25V71.59H89.64V70.25H90.97V68.84H92.3V67.5H89.58V68.84H85.59V71.66H84.19V74.41H82.79V75.75H85.59V75.75ZM85.59,75.75V77.16H81.39M81.39,77.16V74.34H82.79V71.59H84.19V68.84H77.33V77.16H81.39H81.39ZM81.39,77.16V78.43H71.88V77.16H67.75V75.75H66.43V74.34H65.1V73H63.7V71.66H62.37V70.25M62.37,70.25H63.77V71.59H65.1V72.93H66.5V74.34H67.83V75.75H70.55V74.41H69.16V71.66H67.83V68.85H63.7V67.51H60.97V68.85M62.37,70.25H60.98V68.84H62.37V70.25ZM60.97,68.84H59.57V67.43H58.25V55.17H59.65M59.65,55.17V67.44H60.98V66.1H63.77V67.44H67.83V55.17H63.77V56.58H60.98V55.17H59.65ZM69.22,51.08V53.76H75.93V42.84H74.68V44.17H73.28M69.22,51.08H70.62V48.33H71.95V45.58H73.28V44.17H71.88V45.51H70.55V48.26H69.22V51.08ZM69.22,71.59H70.55V74.34H71.95V77.16H75.94V68.84H69.23V71.59H69.22ZM77.34,67.44H84.19V55.17H77.34V67.44ZM69.22,67.44H75.93V55.17H69.22V67.44Z" android:strokeAlpha="0.8" android:strokeColor="#C272FF" android:strokeWidth="0.23451"/>
    
    18
    +      
    
    19
    +    <path android:fillColor="#ffffff" android:pathData="M53.84,42.78H56.64L54.84,40.42L58.14,39.7L55.15,36.24L57.62,36.17L57.73,35.5L41.11,29.32C40.64,29.14 40.17,29 39.7,28.88L31.58,7.75C29.81,3.15 25.32,0.06 20.41,0.06C18.94,0.06 17.49,0.33 16.11,0.87L7.65,4.16C1.5,6.55 -1.57,13.54 0.81,19.73L12.4,49.92C14.17,54.53 18.66,57.62 23.56,57.62C24.22,57.62 24.87,57.57 25.51,57.46C26.74,58.58 28.17,59.46 29.77,60.05L46.5,66.27L44.54,62.76H48.38L47.08,59.56H51.23L49.53,56.39L38.61,52.33C42.24,49.92 44.27,45.7 43.94,41.38L56.68,46.11L53.84,42.78ZM49.04,56.96L50.07,58.86H46.04L47.35,62.07H43.36L44.97,64.96L30.01,59.4C26.89,58.24 24.41,55.93 23.03,52.89C21.64,49.86 21.52,46.48 22.67,43.35L24.89,37.34C25.95,34.46 27.98,32.2 30.46,30.8L33.78,39.46C33.55,39.74 33.36,40.07 33.23,40.44L31.01,46.45C30.68,47.35 30.72,48.31 31.11,49.17C31.5,50.04 32.21,50.7 33.1,51.03L49.04,56.96ZM21.23,46.86C21.17,46.76 21.12,46.65 21.08,46.54L9.48,16.35C9.13,15.45 9.36,14.68 9.53,14.31C9.7,13.93 10.11,13.24 11.01,12.89L19.46,9.6C19.78,9.48 20.1,9.42 20.41,9.42C21.32,9.42 22.44,9.95 22.9,11.14L30.21,30.15C27.54,31.61 25.37,34.02 24.24,37.1L22.02,43.11C21.57,44.33 21.3,45.6 21.23,46.86ZM33.88,40.68C33.93,40.52 34,40.38 34.08,40.24L34.5,41.32C34.85,42.23 34.62,42.99 34.45,43.37H34.45C34.28,43.75 33.88,44.43 32.98,44.78L32.26,45.06L33.88,40.68ZM37.79,52.02L33.34,50.37C32.62,50.11 32.06,49.58 31.74,48.88C31.42,48.19 31.39,47.41 31.66,46.7L31.94,45.93L33.23,45.43C34.36,45 34.87,44.13 35.08,43.65C35.29,43.17 35.58,42.21 35.14,41.07L34.58,39.61V39.59L34.35,39.01L34.32,38.91L31.07,30.48L31.06,30.46L30.85,29.91L30.82,29.82L23.55,10.88C22.97,9.39 21.56,8.72 20.41,8.72C20.01,8.72 19.61,8.8 19.21,8.95L10.76,12.24C9.63,12.68 9.11,13.55 8.9,14.02C8.69,14.5 8.4,15.47 8.84,16.61L20.43,46.8C20.61,47.27 20.88,47.67 21.2,47.97C21.24,49.75 21.64,51.52 22.4,53.18C23.03,54.56 23.87,55.79 24.88,56.85C24.44,56.9 24,56.93 23.56,56.93C18.94,56.93 14.71,54.01 13.04,49.67L1.45,19.48C-0.79,13.65 2.1,7.07 7.9,4.81L16.35,1.52C17.66,1.01 19.03,0.75 20.41,0.75C25.04,0.75 29.26,3.67 30.93,8.01L38.88,28.7L38.91,28.78L39.16,29.43L39.18,29.47L42.53,38.2C42.8,38.9 42.99,39.61 43.11,40.33C43.12,40.35 43.13,40.37 43.13,40.4C43.17,40.61 43.2,40.83 43.22,41.05C43.22,41.07 43.22,41.09 43.22,41.11C43.68,45.46 41.58,49.76 37.79,52.02ZM43.86,40.6C43.74,39.71 43.51,38.81 43.18,37.94L40.01,29.69C40.29,29.77 40.58,29.86 40.87,29.97L55.81,35.53L53.67,35.59L56.85,39.27L53.63,39.97L55.24,42.09H52.33L54.41,44.53L43.86,40.6Z"/>
    
    20
    +      
    
    21
    +    <path android:fillColor="#ffffff" android:pathData="M157.76,99.65L136.71,69.02C134.41,65.69 130.67,63.66 126.65,63.57C125.48,62.52 124.09,61.66 122.51,61.08L107.43,55.47L107.36,55.44L103.68,55.55L106.41,58.69L102.99,59.44L105.06,62.15H102.4L104.54,64.66L115.19,68.62L112.76,70.31C109.62,72.5 107.78,75.86 107.41,79.41L97.62,75.77L99.32,78.92H94.98L96.29,82.12H92.65L94.1,84.72L111.42,91.16C111.59,91.22 111.75,91.28 111.92,91.33L130.63,118.54C132.98,121.96 136.85,124 140.98,124C143.54,124 146.01,123.22 148.12,121.75L154.58,117.26C157.34,115.33 159.19,112.44 159.79,109.12C160.4,105.79 159.68,102.43 157.76,99.65ZM104.95,64.06L103.91,62.85H106.46L104.21,59.89L107.7,59.13L105.17,56.2L107.25,56.14L122.27,61.73C123.5,62.19 124.62,62.82 125.59,63.59C123.31,63.73 121.12,64.49 119.22,65.82L115.89,68.13L104.95,64.06ZM111.65,90.5L111.25,90.35L94.58,84.15L93.84,82.82H97.32L96.01,79.61H100.48L99.1,77.06L107.36,80.13L108.04,80.38L114.5,82.79C115.37,83.11 116.28,83.1 117.1,82.82C117.32,82.75 117.54,82.65 117.74,82.53C118.53,82.1 119.17,81.39 119.5,80.48L120.95,76.56L124.77,73.9C125.25,73.57 125.79,73.39 126.36,73.39C126.8,73.39 127.92,73.51 128.68,74.61L129.76,76.19C129.69,76.47 129.61,76.75 129.51,77.02L127.19,83.33L127.08,83.63C126.11,86.07 124.45,88.03 122.42,89.34C122.23,89.47 122.03,89.59 121.83,89.7C119.04,91.29 115.64,91.75 112.36,90.74C112.13,90.67 111.89,90.59 111.65,90.5ZM117.15,80.21C117.22,79.78 117.48,78.97 118.31,78.39L119.95,77.26L118.85,80.24C118.57,81 118.04,81.58 117.38,81.94C117.04,81.24 117.08,80.57 117.15,80.21ZM130.06,77.56L130.17,77.25C130.2,77.14 130.24,77.04 130.27,76.93L149.73,105.24C150.31,106.08 150.27,106.93 150.19,107.36C150.11,107.79 149.85,108.6 149.02,109.18L142.57,113.67C142.09,114.01 141.55,114.17 140.98,114.17C140.53,114.17 139.41,114.06 138.66,112.95L122.82,89.91C124.96,88.52 126.7,86.46 127.72,83.89L130.06,77.56ZM159.11,108.99C158.54,112.14 156.79,114.87 154.18,116.68L147.73,121.18C145.73,122.57 143.4,123.3 140.98,123.3C137.07,123.3 133.42,121.38 131.2,118.15L112.97,91.63C113.95,91.86 114.94,91.97 115.91,91.97C118.15,91.97 120.32,91.38 122.23,90.28L138.09,113.35C139.03,114.72 140.42,114.87 140.98,114.87C141.7,114.87 142.36,114.66 142.96,114.25L149.42,109.75C150.45,109.03 150.77,108.02 150.87,107.48C150.96,106.95 151.02,105.89 150.3,104.85L130.51,76.06L129.97,75.26L129.25,74.22C128.3,72.84 126.91,72.7 126.36,72.7H126.36C125.64,72.7 124.97,72.91 124.38,73.32L121.37,75.42L120.37,76.11L117.92,77.82C116.88,78.54 116.56,79.55 116.46,80.08C116.39,80.53 116.33,81.34 116.74,82.2C116.1,82.39 115.41,82.38 114.74,82.13L108.08,79.66C108.39,76.25 110.14,72.99 113.15,70.89L115.99,68.91L116.68,68.43L119.61,66.39C121.6,65 123.94,64.27 126.36,64.27H126.37C126.72,64.27 127.07,64.28 127.41,64.31C130.91,64.62 134.12,66.48 136.13,69.42L157.19,100.05C159,102.68 159.68,105.85 159.11,108.99Z"/>
    
    22
    +      
    
    23
    +    <path android:fillColor="#C272FF" android:pathData="M26.73,77.81L30.91,77.83L30.91,79.04L26.73,79.03V84.32H25.51V79.03L21.2,79.02L21.2,77.8L25.51,77.81V72.54H26.73V77.81Z"/>
    
    24
    +      
    
    25
    +    <path android:fillColor="#C272FF" android:pathData="M132.82,37.87L137,37.88L137,39.08L132.82,39.07V44.31H131.6V39.07L127.29,39.06L127.29,37.85L131.6,37.86V32.65H132.82V37.87Z"/>
    
    26
    +      
    
    27
    +    <path android:fillColor="#C272FF" android:pathData="M20.17,99.2C20.17,98.79 19.84,98.46 19.43,98.46C19.02,98.46 18.69,98.79 18.69,99.2C18.69,99.62 19.02,99.95 19.43,99.95V101.17C18.36,101.17 17.49,100.29 17.49,99.2C17.49,98.12 18.36,97.24 19.43,97.24C20.51,97.24 21.38,98.12 21.38,99.2C21.38,100.29 20.51,101.17 19.43,101.17V99.95C19.84,99.95 20.17,99.62 20.17,99.2Z"/>
    
    28
    +      
    
    29
    +    <path android:fillColor="#C272FF" android:pathData="M116.28,43.22C117.35,43.22 118.22,44.1 118.22,45.18C118.22,46.27 117.35,47.15 116.28,47.15C115.2,47.15 114.33,46.27 114.33,45.18C114.33,44.1 115.2,43.22 116.28,43.22Z"/>
    
    30
    +      
    
    31
    +    <path android:fillColor="#C272FF" android:pathData="M134.74,51.08C135.81,51.08 136.68,51.96 136.68,53.04C136.68,54.12 135.81,55 134.74,55C133.66,55 132.79,54.12 132.79,53.04C132.79,51.96 133.66,51.08 134.74,51.08Z"/>
    
    32
    +      
    
    33
    +    <path android:fillColor="#C272FF" android:pathData="M32.81,91.67C32.81,91.26 32.47,90.93 32.06,90.93C31.66,90.93 31.32,91.26 31.32,91.67C31.32,92.09 31.66,92.42 32.06,92.42V93.64C30.99,93.64 30.12,92.76 30.12,91.67C30.12,90.59 30.99,89.71 32.06,89.71C33.14,89.71 34.01,90.59 34.01,91.67C34.01,92.76 33.14,93.64 32.06,93.64V92.42C32.47,92.42 32.81,92.09 32.81,91.67Z"/>
    
    34
    +    
    
    35
    +</vector>

  • mobile/android/fenix/app/src/main/res/drawable/heart.xml
    1
    +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="16dp" android:viewportHeight="16" android:viewportWidth="16" android:width="16dp">
    
    2
    +      
    
    3
    +    <path android:fillColor="#FBFBFE" android:pathData="M8,6C8,6 8,2 11.5,2C15,2 15,5 15,6C15,10.5 8,15 8,15V6Z"/>
    
    4
    +      
    
    5
    +    <path android:fillColor="#FBFBFE" android:pathData="M8,6C8,6 8,2 4.5,2C1,2 1,5 1,6C1,10.5 8,15 8,15L9,9L8,6Z"/>
    
    6
    +    
    
    7
    +</vector>

  • mobile/android/fenix/app/src/main/res/drawable/yec_lightning.xml
    1
    +<vector xmlns:android="http://schemas.android.com/apk/res/android"
    
    2
    +    android:width="18dp"
    
    3
    +    android:height="18dp"
    
    4
    +    android:viewportWidth="18"
    
    5
    +    android:viewportHeight="18">
    
    6
    +  <path
    
    7
    +      android:pathData="M16.469,7.826C16.396,7.63 16.209,7.5 16,7.5H9.963L13.445,0.729C13.554,0.516 13.498,0.255 13.309,0.108C13.219,0.036 13.109,0 13,0C12.884,0 12.767,0.041 12.674,0.122L9,3.294L1.674,9.622C1.516,9.758 1.459,9.979 1.532,10.174C1.605,10.37 1.791,10.5 2,10.5H8.038L4.555,17.271C4.446,17.484 4.502,17.744 4.691,17.892C4.782,17.965 4.891,18 5,18C5.117,18 5.233,17.959 5.327,17.878L9,14.706L16.326,8.378C16.485,8.242 16.542,8.021 16.469,7.826Z"
    
    8
    +      android:fillColor="#FFAC33"/>
    
    9
    +</vector>

  • mobile/android/fenix/app/src/main/res/values/torbrowser_strings.xml
    ... ... @@ -153,4 +153,11 @@
    153 153
         <!-- Year End Campaign. Here "Close" is a verb, referring to closing the banner. This is used primarily for screen readers to give the small "x" button a name. -->
    
    154 154
         <string name="close_yec_button_description">Close</string>
    
    155 155
     
    
    156
    +    <!-- Year End Campaign 2026. Title text. -->
    
    157
    +    <string name="yec26_tor_powered_by_you">Tor: powered by you</string>
    
    158
    +    <!-- Year End Campaign 2026. Main body text. -->
    
    159
    +    <string name="yec26_call_to_action">Unlike Big Tech, Tor doesn’t sell your data to make money. Instead, 6,490 donors every year keep Tor strong. Join the movement with a donation today!</string>
    
    160
    +    <!-- Year End Campaign 2026. Main image description. -->
    
    161
    +    <string name="bulb_illo_yec_description">Illustration of a pink hand reaching to turn on a pink light bulb on a violet background. The light bulb vaguely resembles an onion with greens coming out of the top. There are playful bolts coming out of the bulb, and a green heart on the sleeve of the shirt.</string>
    
    162
    +
    
    156 163
     </resources>

  • _______________________________________________
    tor-commits mailing list -- tor-commits@xxxxxxxxxxxxxxxxxxxx
    To unsubscribe send an email to tor-commits-leave@xxxxxxxxxxxxxxxxxxxx