feat: experimental font selection with google sans flex

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2025-11-29 13:33:56 +01:00
parent e07660c0e2
commit a6883f2b8e
14 changed files with 378 additions and 4 deletions

View File

@ -146,6 +146,7 @@ fun InviteScreen(
StoatTheme( StoatTheme(
requestedTheme = LoadedSettings.theme, requestedTheme = LoadedSettings.theme,
requestedUserInterfaceFont = LoadedSettings.font,
colourOverrides = SyncedSettings.android.colourOverrides colourOverrides = SyncedSettings.android.colourOverrides
) { ) {
Surface( Surface(

View File

@ -481,6 +481,7 @@ fun AppEntrypoint(
StoatTheme( StoatTheme(
requestedTheme = LoadedSettings.theme, requestedTheme = LoadedSettings.theme,
requestedUserInterfaceFont = LoadedSettings.font,
colourOverrides = SyncedSettings.android.colourOverrides colourOverrides = SyncedSettings.android.colourOverrides
) { ) {
Box( Box(

View File

@ -279,6 +279,7 @@ fun ShareTargetScreen(
StoatTheme( StoatTheme(
requestedTheme = LoadedSettings.theme, requestedTheme = LoadedSettings.theme,
requestedUserInterfaceFont = LoadedSettings.font,
colourOverrides = SyncedSettings.android.colourOverrides colourOverrides = SyncedSettings.android.colourOverrides
) { ) {
Scaffold( Scaffold(

View File

@ -184,6 +184,7 @@ fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
StoatTheme( StoatTheme(
requestedTheme = LoadedSettings.theme, requestedTheme = LoadedSettings.theme,
requestedUserInterfaceFont = LoadedSettings.font,
colourOverrides = SyncedSettings.android.colourOverrides colourOverrides = SyncedSettings.android.colourOverrides
) { ) {
Scaffold( Scaffold(

View File

@ -58,6 +58,7 @@ import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import chat.stoat.R import chat.stoat.R
import chat.stoat.api.settings.UserInterfaceFont
import chat.stoat.composables.generic.Presence import chat.stoat.composables.generic.Presence
import chat.stoat.composables.generic.RemoteImage import chat.stoat.composables.generic.RemoteImage
import chat.stoat.composables.generic.presenceColour import chat.stoat.composables.generic.presenceColour
@ -81,7 +82,8 @@ class IncomingActivity : ComponentActivity() {
@Composable @Composable
fun IncomingCall() { fun IncomingCall() {
StoatTheme( StoatTheme(
requestedTheme = if (isSystemInDarkTheme()) Theme.Default else Theme.Light requestedTheme = if (isSystemInDarkTheme()) Theme.Default else Theme.Light,
requestedUserInterfaceFont = UserInterfaceFont.Default
) { ) {
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) { CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) {
IncomingCallInner() IncomingCallInner()

View File

@ -43,6 +43,11 @@ data class AndroidSpecificSettings(
* Can be one of `{ None, Default, Light, M3Dynamic, Amoled }` * Can be one of `{ None, Default, Light, M3Dynamic, Amoled }`
*/ */
var theme: String? = null, var theme: String? = null,
/**
* The font to use for the app.
* Can be one of `{ Default, GoogleSansFlex }`
*/
var font: String? = null,
/** /**
* Colour overrides. * Colour overrides.
* Map of `primary, onPrimary, primaryContainer, onPrimaryContainer, inversePrimary, secondary, onSecondary, secondaryContainer, onSecondaryContainer, tertiary, onTertiary, tertiaryContainer, onTertiaryContainer, background, onBackground, surface, onSurface, surfaceVariant, onSurfaceVariant, surfaceTint, inverseSurface, inverseOnSurface, error, onError, errorContainer, onErrorContainer, outline, outlineVariant, scrim` to int colours. * Map of `primary, onPrimary, primaryContainer, onPrimaryContainer, inversePrimary, secondary, onSecondary, secondaryContainer, onSecondaryContainer, tertiary, onTertiary, tertiaryContainer, onTertiaryContainer, background, onBackground, surface, onSurface, surfaceVariant, onSurfaceVariant, surfaceTint, inverseSurface, inverseOnSurface, error, onError, errorContainer, onErrorContainer, outline, outlineVariant, scrim` to int colours.

View File

@ -14,6 +14,11 @@ enum class MessageReplyStyle {
DoubleTap DoubleTap
} }
enum class UserInterfaceFont {
Default,
GoogleSansFlex,
}
typealias SpecialEmbedSettings = AndroidSpecificSettingsSpecialEmbedSettings typealias SpecialEmbedSettings = AndroidSpecificSettingsSpecialEmbedSettings
object LoadedSettings { object LoadedSettings {
@ -23,6 +28,7 @@ object LoadedSettings {
var experimentsEnabled by mutableStateOf(false) var experimentsEnabled by mutableStateOf(false)
var specialEmbedSettings by mutableStateOf(SpecialEmbedSettings()) var specialEmbedSettings by mutableStateOf(SpecialEmbedSettings())
var poorlyFormedSettingsKeys by mutableStateOf(emptySet<String>()) var poorlyFormedSettingsKeys by mutableStateOf(emptySet<String>())
var font by mutableStateOf(UserInterfaceFont.Default)
fun hydrateWithSettings(settings: SyncedSettings) { fun hydrateWithSettings(settings: SyncedSettings) {
this.theme = settings.android.theme?.let { this.theme = settings.android.theme?.let {
@ -33,6 +39,13 @@ object LoadedSettings {
?: MessageReplyStyle.SwipeFromEnd ?: MessageReplyStyle.SwipeFromEnd
this.avatarRadius = settings.android.avatarRadius ?: 50 this.avatarRadius = settings.android.avatarRadius ?: 50
this.specialEmbedSettings = settings.android.specialEmbedSettings ?: SpecialEmbedSettings() this.specialEmbedSettings = settings.android.specialEmbedSettings ?: SpecialEmbedSettings()
this.font = settings.android.font?.let {
try {
UserInterfaceFont.valueOf(it)
} catch (e: Exception) {
null
}
} ?: UserInterfaceFont.Default
} }
fun reset() { fun reset() {
@ -41,5 +54,6 @@ object LoadedSettings {
avatarRadius = 50 avatarRadius = 50
specialEmbedSettings = SpecialEmbedSettings() specialEmbedSettings = SpecialEmbedSettings()
poorlyFormedSettingsKeys = emptySet() poorlyFormedSettingsKeys = emptySet()
font = UserInterfaceFont.Default
} }
} }

View File

@ -27,6 +27,7 @@ object SyncedSettings {
private val _android = mutableStateOf( private val _android = mutableStateOf(
AndroidSpecificSettings( AndroidSpecificSettings(
theme = "None", theme = "None",
font = "Default",
colourOverrides = null, colourOverrides = null,
messageReplyStyle = "None" messageReplyStyle = "None"
) )
@ -130,6 +131,7 @@ object SyncedSettings {
suspend fun resetAndroid() { suspend fun resetAndroid() {
val default = AndroidSpecificSettings( val default = AndroidSpecificSettings(
theme = "None", theme = "None",
font = "Default",
colourOverrides = null, colourOverrides = null,
messageReplyStyle = "None" messageReplyStyle = "None"
) )

View File

@ -23,7 +23,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ButtonGroupDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.LargeTopAppBar
@ -32,6 +34,7 @@ import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.ToggleButton
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
@ -50,6 +53,9 @@ import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -62,10 +68,13 @@ import chat.stoat.api.StoatCbor
import chat.stoat.api.StoatJson import chat.stoat.api.StoatJson
import chat.stoat.api.settings.LoadedSettings import chat.stoat.api.settings.LoadedSettings
import chat.stoat.api.settings.SyncedSettings import chat.stoat.api.settings.SyncedSettings
import chat.stoat.api.settings.UserInterfaceFont
import chat.stoat.composables.generic.ListHeader import chat.stoat.composables.generic.ListHeader
import chat.stoat.composables.screens.settings.appearance.ColourChip import chat.stoat.composables.screens.settings.appearance.ColourChip
import chat.stoat.composables.screens.settings.appearance.CornerRadiusPicker import chat.stoat.composables.screens.settings.appearance.CornerRadiusPicker
import chat.stoat.sheets.ColourPickerSheet import chat.stoat.sheets.ColourPickerSheet
import chat.stoat.ui.theme.GoogleSansFlex
import chat.stoat.ui.theme.Inter
import chat.stoat.ui.theme.OverridableColourScheme import chat.stoat.ui.theme.OverridableColourScheme
import chat.stoat.ui.theme.Theme import chat.stoat.ui.theme.Theme
import chat.stoat.ui.theme.getFieldByName import chat.stoat.ui.theme.getFieldByName
@ -96,6 +105,13 @@ class AppearanceSettingsScreenViewModel @Inject constructor(
} }
} }
fun saveNewFont(font: UserInterfaceFont) {
LoadedSettings.font = font
viewModelScope.launch {
SyncedSettings.updateAndroid(SyncedSettings.android.copy(font = font.name))
}
}
fun saveNewAvatarRadius(radius: Int) { fun saveNewAvatarRadius(radius: Int) {
LoadedSettings.avatarRadius = radius LoadedSettings.avatarRadius = radius
viewModelScope.launch { viewModelScope.launch {
@ -198,7 +214,10 @@ class AppearanceSettingsScreenViewModel @Inject constructor(
} }
} }
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class) @OptIn(
ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class,
ExperimentalMaterial3ExpressiveApi::class
)
@Composable @Composable
fun AppearanceSettingsScreen( fun AppearanceSettingsScreen(
navController: NavController, navController: NavController,
@ -391,6 +410,45 @@ fun AppearanceSettingsScreen(
} }
} }
ListHeader {
Text(stringResource(R.string.settings_appearance_typeface))
}
FlowRow(
Modifier
.padding(horizontal = 8.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(ButtonGroupDefaults.ConnectedSpaceBetween),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
ToggleButton(
checked = LoadedSettings.font == UserInterfaceFont.Default,
onCheckedChange = { viewModel.saveNewFont(UserInterfaceFont.Default) },
shapes = ButtonGroupDefaults.connectedLeadingButtonShapes(),
modifier = Modifier
.semantics { role = Role.RadioButton }
.weight(1f),
) {
Text(
stringResource(R.string.settings_appearance_typeface_default),
fontFamily = Inter
)
}
ToggleButton(
checked = LoadedSettings.font == UserInterfaceFont.GoogleSansFlex,
onCheckedChange = { viewModel.saveNewFont(UserInterfaceFont.GoogleSansFlex) },
shapes = ButtonGroupDefaults.connectedTrailingButtonShapes(),
modifier = Modifier
.semantics { role = Role.RadioButton }
.weight(1f),
) {
Text(
stringResource(R.string.settings_appearance_typeface_google_sans_flex),
fontFamily = GoogleSansFlex
)
}
}
ListHeader { ListHeader {
Text(stringResource(R.string.settings_appearance_avatar_shape)) Text(stringResource(R.string.settings_appearance_avatar_shape))
} }

View File

@ -17,6 +17,7 @@ import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import chat.stoat.api.settings.UserInterfaceFont
val LightColorScheme = lightColorScheme( val LightColorScheme = lightColorScheme(
primary = Colour.PrimaryLight, primary = Colour.PrimaryLight,
@ -172,14 +173,19 @@ fun getColorScheme(
@Composable @Composable
fun StoatTheme( fun StoatTheme(
requestedTheme: Theme, requestedTheme: Theme,
requestedUserInterfaceFont: UserInterfaceFont,
colourOverrides: OverridableColourScheme? = null, colourOverrides: OverridableColourScheme? = null,
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
val colorScheme = getColorScheme(requestedTheme, colourOverrides) val colorScheme = getColorScheme(requestedTheme, colourOverrides)
val typography = when (requestedUserInterfaceFont) {
UserInterfaceFont.Default -> StoatTypography
UserInterfaceFont.GoogleSansFlex -> GoogleTypography
}
MaterialTheme( MaterialTheme(
colorScheme = colorScheme, colorScheme = colorScheme,
typography = StoatTypography, typography = typography,
content = content content = content
) )
} }

View File

@ -1,15 +1,17 @@
package chat.stoat.ui.theme package chat.stoat.ui.theme
import androidx.compose.material3.Typography import androidx.compose.material3.Typography
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontVariation
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import chat.stoat.R import chat.stoat.R
private val Inter = FontFamily( val Inter = FontFamily(
Font(R.font.inter_thin, FontWeight.Thin), Font(R.font.inter_thin, FontWeight.Thin),
Font(R.font.inter_extralight, FontWeight.ExtraLight), Font(R.font.inter_extralight, FontWeight.ExtraLight),
Font(R.font.inter_light, FontWeight.Light), Font(R.font.inter_light, FontWeight.Light),
@ -54,6 +56,190 @@ val FragmentMono = FontFamily(
Font(R.font.fragmentmono_italic, FontWeight.Normal, FontStyle.Italic) Font(R.font.fragmentmono_italic, FontWeight.Normal, FontStyle.Italic)
) )
@OptIn(ExperimentalTextApi::class)
val GoogleSansFlex = FontFamily(
Font(
R.font.googlesansflex,
FontWeight.Thin,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(100),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.ExtraLight,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(200),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Light,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(300),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Normal,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(400),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Medium,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(500),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.SemiBold,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(600),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Bold,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(700),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.ExtraBold,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(800),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Black,
FontStyle.Normal,
variationSettings = FontVariation.Settings(
FontVariation.weight(900),
FontVariation.width(100f),
FontVariation.slant(0f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Thin,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(100),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.ExtraLight,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(200),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Light,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(300),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Normal,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(400),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Medium,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(500),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.SemiBold,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(600),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Bold,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(700),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.ExtraBold,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(800),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
),
Font(
R.font.googlesansflex,
FontWeight.Black,
FontStyle.Italic,
variationSettings = FontVariation.Settings(
FontVariation.weight(900),
FontVariation.width(100f),
FontVariation.slant(-10f),
)
)
)
val StoatTypography = Typography( val StoatTypography = Typography(
displayLarge = TextStyle( displayLarge = TextStyle(
fontFamily = InterDisplay, fontFamily = InterDisplay,
@ -135,3 +321,81 @@ val StoatTypography = Typography(
fontSize = 12.sp fontSize = 12.sp
) )
) )
val GoogleTypography = Typography(
displayLarge = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Black,
fontSize = 57.sp
),
displayMedium = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.ExtraBold,
fontSize = 45.sp
),
displaySmall = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Bold,
fontSize = 36.sp
),
headlineLarge = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.SemiBold,
fontSize = 32.sp
),
headlineMedium = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.SemiBold,
fontSize = 28.sp
),
headlineSmall = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Bold,
fontSize = 24.sp
),
titleLarge = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.SemiBold,
fontSize = 22.sp
),
titleMedium = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.SemiBold,
fontSize = 16.sp
),
titleSmall = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Bold,
fontSize = 14.sp
),
labelLarge = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.SemiBold,
fontSize = 14.sp
),
labelMedium = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Bold,
fontSize = 12.sp
),
labelSmall = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Bold,
fontSize = 11.sp
),
bodyLarge = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
bodyMedium = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
),
bodySmall = TextStyle(
fontFamily = GoogleSansFlex,
fontWeight = FontWeight.Bold,
fontSize = 12.sp
)
)

Binary file not shown.

View File

@ -708,6 +708,9 @@
<string name="settings_appearance_theme_m3dynamic">Material You</string> <string name="settings_appearance_theme_m3dynamic">Material You</string>
<string name="settings_appearance_theme_m3dynamic_unsupported">Material You (unsupported)</string> <string name="settings_appearance_theme_m3dynamic_unsupported">Material You (unsupported)</string>
<string name="settings_appearance_theme_m3dynamic_unsupported_toast">Material You is not supported on this device.</string> <string name="settings_appearance_theme_m3dynamic_unsupported_toast">Material You is not supported on this device.</string>
<string name="settings_appearance_typeface">Font</string>
<string name="settings_appearance_typeface_default">Default</string>
<string name="settings_appearance_typeface_google_sans_flex" translatable="false">Google Sans Flex</string>
<string name="settings_appearance_avatar_shape">Profile Picture Shape</string> <string name="settings_appearance_avatar_shape">Profile Picture Shape</string>
<string name="settings_appearance_avatar_shape_description">Choose the rounding grade for profile pictures, including in chat and profiles. This applies to all users.</string> <string name="settings_appearance_avatar_shape_description">Choose the rounding grade for profile pictures, including in chat and profiles. This applies to all users.</string>

View File

@ -0,0 +1,16 @@
{
"uniqueId": "com.google.fonts:googlesansflex:0.0.0",
"developers": [
{
"name": "Google",
"organisationUrl": "https://about.google/"
}
],
"artifactVersion": "0.0.0",
"description": "Google Sans Flex is the next generation of Googles brand typeface.",
"name": "Google Sans Flex",
"website": "https://fonts.google.com/specimen/Google+Sans+Flex",
"licenses": [
"OFL"
]
}