This commit is contained in:
Andrew 2024-06-12 01:13:47 +09:30
parent 50f9864a8b
commit 3c36f1247b
17 changed files with 387 additions and 91 deletions

View File

@ -52,7 +52,8 @@ fun DisappearingMessages(
OptionsCard(it, callbacks)
}
if (state.showGroupFooter) Text(text = stringResource(R.string.activity_disappearing_messages_group_footer),
if (state.showGroupFooter) Text(
text = stringResource(R.string.activity_disappearing_messages_group_footer),
style = MaterialTheme.typography.extraSmall,
fontWeight = FontWeight(400),
color = Color(0xFFA1A2A1),

View File

@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.ui.LoadingArcOr
import org.thoughtcrime.securesms.ui.PreviewTheme
import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider
import org.thoughtcrime.securesms.ui.baseBold
import org.thoughtcrime.securesms.ui.components.AppBar
import org.thoughtcrime.securesms.ui.components.BorderlessButtonSecondary
import org.thoughtcrime.securesms.ui.components.MaybeScanQrCode
@ -175,7 +176,10 @@ fun EnterAccountId(
onClick = { callbacks.onContinue() }
) {
LoadingArcOr(state.loading) {
Text(stringResource(R.string.next))
Text(
stringResource(R.string.next),
style = MaterialTheme.typography.baseBold
)
}
}
}

View File

@ -33,6 +33,8 @@ import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.preferences.copyPublicKey
import org.thoughtcrime.securesms.preferences.sendInvitationToUseSession
import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.ui.base
import org.thoughtcrime.securesms.ui.baseBold
import org.thoughtcrime.securesms.ui.classicDarkColors
import org.thoughtcrime.securesms.ui.components.AppBar
import org.thoughtcrime.securesms.ui.components.OnPrimaryButtons
@ -53,6 +55,7 @@ class InviteFriendFragment : Fragment() {
setContent {
AppTheme {
InviteFriend(
TextSecurePreferences.getLocalNumber(LocalContext.current)!!,
onBack = { delegate.onDialogBackPressed() },
onClose = { delegate.onDialogClosePressed() },
copyPublicKey = requireContext()::copyPublicKey,
@ -66,11 +69,12 @@ class InviteFriendFragment : Fragment() {
@Preview
@Composable
private fun PreviewInviteFriend() {
InviteFriend()
InviteFriend("050000000")
}
@Composable
private fun InviteFriend(
accountId: String,
onBack: () -> Unit = {},
onClose: () -> Unit = {},
copyPublicKey: () -> Unit = {},
@ -93,12 +97,13 @@ private fun InviteFriend(
.wrapContentHeight()
) {
Text(
TextSecurePreferences.getLocalNumber(LocalContext.current)!!,
textAlign = TextAlign.Center,
accountId,
modifier = Modifier
.contentDescription("Your account ID")
.align(Alignment.Center)
.padding(22.dp)
.padding(22.dp),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.base
)
}
@ -118,7 +123,10 @@ private fun InviteFriend(
.contentDescription("Share button"),
onClick = sendInvitation
) {
Text(stringResource(R.string.share))
Text(
stringResource(R.string.share),
style = MaterialTheme.typography.baseBold
)
}
OutlineTemporaryStateButton(
@ -127,7 +135,10 @@ private fun InviteFriend(
.contentDescription(R.string.AccessibilityId_copy_button),
onClick = copyPublicKey
) { isTemporary ->
Text(stringResource(if (isTemporary) R.string.copied else R.string.copy))
Text(
stringResource(if (isTemporary) R.string.copied else R.string.copy),
style = MaterialTheme.typography.baseBold
)
}
}
}

View File

@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.fragment.app.Fragment
import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.R
@ -29,8 +28,8 @@ import org.thoughtcrime.securesms.ui.classicDarkColors
import org.thoughtcrime.securesms.ui.components.AppBar
import org.thoughtcrime.securesms.ui.components.QrImage
import org.thoughtcrime.securesms.ui.contentDescription
import org.thoughtcrime.securesms.ui.medium
import org.thoughtcrime.securesms.ui.small
import org.thoughtcrime.securesms.ui.xl
import javax.inject.Inject
@AndroidEntryPoint
@ -67,10 +66,18 @@ class NewConversationHomeFragment : Fragment() {
Column(
modifier = Modifier
.padding(horizontal = LocalDimensions.current.marginMedium)
.padding(top = LocalDimensions.current.itemSpacingMedium)) {
Text(text = stringResource(R.string.accountIdYours), style = MaterialTheme.typography.medium)
.padding(top = LocalDimensions.current.itemSpacingMedium)
) {
Text(
text = stringResource(R.string.accountIdYours),
style = MaterialTheme.typography.xl
)
Spacer(modifier = Modifier.height(LocalDimensions.current.itemSpacingTiny))
Text(text = stringResource(R.string.qrYoursDescription), color = classicDarkColors[5], style = MaterialTheme.typography.small)
Text(
text = stringResource(R.string.qrYoursDescription),
color = classicDarkColors[5],
style = MaterialTheme.typography.small
)
Spacer(modifier = Modifier.height(LocalDimensions.current.itemSpacingSmall))
QrImage(string = TextSecurePreferences.getLocalNumber(requireContext())!!, Modifier.contentDescription(R.string.AccessibilityId_qr_code))
}

View File

@ -29,6 +29,7 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Icon
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
@ -72,6 +73,9 @@ import org.thoughtcrime.securesms.ui.ItemButton
import org.thoughtcrime.securesms.ui.PreviewTheme
import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider
import org.thoughtcrime.securesms.ui.TitledText
import org.thoughtcrime.securesms.ui.base
import org.thoughtcrime.securesms.ui.baseBold
import org.thoughtcrime.securesms.ui.baseMonospace
import org.thoughtcrime.securesms.ui.blackAlpha40
import org.thoughtcrime.securesms.ui.colorDestructive
import org.thoughtcrime.securesms.ui.destructiveButtonColors
@ -364,7 +368,7 @@ fun FileDetails(fileDetails: List<TitledText>) {
fun TitledErrorText(titledText: TitledText?) {
TitledText(
titledText,
style = LocalTextStyle.current.copy(color = colorDestructive)
style = MaterialTheme.typography.base.copy(color = colorDestructive)
)
}
@ -372,7 +376,7 @@ fun TitledErrorText(titledText: TitledText?) {
fun TitledMonospaceText(titledText: TitledText?) {
TitledText(
titledText,
style = LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace)
style = MaterialTheme.typography.baseMonospace
)
}
@ -380,11 +384,15 @@ fun TitledMonospaceText(titledText: TitledText?) {
fun TitledText(
titledText: TitledText?,
modifier: Modifier = Modifier,
style: TextStyle = LocalTextStyle.current,
style: TextStyle = MaterialTheme.typography.base,
) {
titledText?.apply {
TitledView(title, modifier) {
Text(text, style = style, modifier = Modifier.fillMaxWidth())
Text(
text,
style = style,
modifier = Modifier.fillMaxWidth()
)
}
}
}
@ -399,5 +407,8 @@ fun TitledView(title: GetString, modifier: Modifier = Modifier, content: @Compos
@Composable
fun Title(title: GetString) {
Text(title.string(), fontWeight = FontWeight.Bold)
Text(
title.string(),
style = MaterialTheme.typography.baseBold
)
}

View File

@ -98,9 +98,11 @@ import org.thoughtcrime.securesms.preferences.SettingsActivity
import org.thoughtcrime.securesms.showMuteDialog
import org.thoughtcrime.securesms.showSessionDialog
import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.ui.LocalDimensions
import org.thoughtcrime.securesms.ui.PreviewTheme
import org.thoughtcrime.securesms.ui.SessionShieldIcon
import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider
import org.thoughtcrime.securesms.ui.base
import org.thoughtcrime.securesms.ui.components.OutlineButton
import org.thoughtcrime.securesms.ui.contentDescription
import org.thoughtcrime.securesms.ui.h8
@ -372,25 +374,33 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
private fun SeedReminder() {
AppTheme {
Column {
// Color Strip
Box(
Modifier
.fillMaxWidth()
.height(4.dp)
.background(MaterialTheme.colors.secondary))
.background(MaterialTheme.colors.secondary)
)
Row(
Modifier
.background(MaterialTheme.colors.surface)
.padding(horizontal = 24.dp, vertical = 16.dp)
.padding(horizontal = LocalDimensions.current.marginSmall, vertical = LocalDimensions.current.marginExtraSmall)
) {
Column(Modifier.weight(1f)) {
Row {
Text(stringResource(R.string.save_your_recovery_password), style = MaterialTheme.typography.h8)
Spacer(Modifier.requiredWidth(8.dp))
Text(
stringResource(R.string.save_your_recovery_password),
style = MaterialTheme.typography.h8
)
Spacer(Modifier.requiredWidth(LocalDimensions.current.itemSpacingSmall))
SessionShieldIcon()
}
Text(stringResource(R.string.save_your_recovery_password_to_make_sure_you_don_t_lose_access_to_your_account), style = MaterialTheme.typography.small)
Text(
stringResource(R.string.save_your_recovery_password_to_make_sure_you_don_t_lose_access_to_your_account),
style = MaterialTheme.typography.small
)
}
Spacer(Modifier.width(12.dp))
Spacer(Modifier.width(LocalDimensions.current.marginExtraExtraSmall))
OutlineButton(
textId = R.string.continue_2,
modifier = Modifier
@ -418,27 +428,38 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
contentDescription = null,
tint = Color.Unspecified
)
if (newAccount) Text(stringResource(R.string.onboardingAccountCreated), style = MaterialTheme.typography.h4, textAlign = TextAlign.Center)
if (newAccount) Text(stringResource(R.string.welcome_to_session), color = MaterialTheme.colors.secondary, textAlign = TextAlign.Center)
if (newAccount) {
Text(
stringResource(R.string.onboardingAccountCreated),
style = MaterialTheme.typography.h4,
textAlign = TextAlign.Center
)
Text(
stringResource(R.string.welcome_to_session),
style = MaterialTheme.typography.base,
color = MaterialTheme.colors.secondary,
textAlign = TextAlign.Center
)
}
Divider(modifier = Modifier.padding(vertical = 16.dp))
Divider(modifier = Modifier.padding(vertical = LocalDimensions.current.marginExtraSmall))
Text(
stringResource(R.string.conversationsNone),
style = MaterialTheme.typography.h8,
textAlign = TextAlign.Center,
modifier = Modifier.padding(bottom = 12.dp))
Text(stringResource(R.string.onboardingHitThePlusButton), textAlign = TextAlign.Center)
Text(
stringResource(R.string.onboardingHitThePlusButton),
style = MaterialTheme.typography.small,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.weight(2f))
}
}
}
override fun onInputFocusChanged(hasFocus: Boolean) {
if (hasFocus) {
setSearchShown(true)
} else {
setSearchShown(binding.globalSearchInputLayout.query.value.isNotEmpty())
}
setSearchShown(hasFocus || binding.globalSearchInputLayout.query.value.isNotEmpty())
}
private fun setSearchShown(isShown: Boolean) {

View File

@ -8,7 +8,6 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.slideInVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -49,12 +48,12 @@ import org.thoughtcrime.securesms.onboarding.pickname.startPickDisplayNameActivi
import org.thoughtcrime.securesms.service.KeyCachingService
import org.thoughtcrime.securesms.showOpenUrlDialog
import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.ui.Cell
import org.thoughtcrime.securesms.ui.LocalDimensions
import org.thoughtcrime.securesms.ui.PreviewTheme
import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider
import org.thoughtcrime.securesms.ui.classicDarkColors
import org.thoughtcrime.securesms.ui.components.BorderlessButton
import org.thoughtcrime.securesms.ui.components.BorderlessHtmlButton
import org.thoughtcrime.securesms.ui.components.FilledButton
import org.thoughtcrime.securesms.ui.components.OutlineButton
import org.thoughtcrime.securesms.ui.contentDescription
@ -173,8 +172,8 @@ class LandingActivity : BaseActionBarActivity() {
.align(Alignment.CenterHorizontally)
.contentDescription(R.string.AccessibilityId_restore_account_button)
) { start<LinkDeviceActivity>() }
BorderlessButton(
text = stringResource(R.string.onboardingTosPrivacy),
BorderlessHtmlButton(
textId = R.string.onboardingTosPrivacy,
modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally)

View File

@ -33,6 +33,8 @@ import network.loki.messenger.R
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.ui.LocalDimensions
import org.thoughtcrime.securesms.ui.base
import org.thoughtcrime.securesms.ui.baseBold
import org.thoughtcrime.securesms.ui.components.MaybeScanQrCode
import org.thoughtcrime.securesms.ui.components.OutlineButton
@ -113,11 +115,14 @@ fun PreviewRecoveryPassword() = RecoveryPassword(state = LinkDeviceState())
@Composable
fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, onContinue: () -> Unit = {}) {
Column(
modifier = Modifier.padding(horizontal = 60.dp)
modifier = Modifier.padding(horizontal = LocalDimensions.current.marginLarge)
) {
Spacer(Modifier.weight(1f))
Row {
Text(stringResource(R.string.sessionRecoveryPassword), style = MaterialTheme.typography.h4)
Text(
stringResource(R.string.sessionRecoveryPassword),
style = MaterialTheme.typography.h4
)
Spacer(Modifier.width(6.dp))
Icon(
painter = painterResource(id = R.drawable.ic_shield_outline),
@ -125,7 +130,10 @@ fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, on
)
}
Spacer(Modifier.size(28.dp))
Text(stringResource(R.string.activity_link_enter_your_recovery_password_to_load_your_account_if_you_haven_t_saved_it_you_can_find_it_in_your_app_settings))
Text(
stringResource(R.string.activity_link_enter_your_recovery_password_to_load_your_account_if_you_haven_t_saved_it_you_can_find_it_in_your_app_settings),
style = MaterialTheme.typography.base
)
Spacer(Modifier.size(24.dp))
SessionOutlinedTextField(
text = state.recoveryPhrase,
@ -137,24 +145,14 @@ fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, on
onContinue = onContinue,
error = state.error
)
Spacer(Modifier.size(12.dp))
state.error?.let {
Text(
it,
modifier = Modifier.contentDescription(R.string.AccessibilityId_error_message),
style = MaterialTheme.typography.baseBold,
color = MaterialTheme.colors.error
)
}
Spacer(Modifier.weight(2f))
OutlineButton(
textId = R.string.continue_2,
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(horizontal = 64.dp, vertical = 20.dp)
.padding(horizontal = LocalDimensions.current.marginLarge, vertical = 20.dp)
.width(200.dp),
onClick = onContinue
)
}
}

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentWidth
@ -35,9 +36,11 @@ import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.showSessionDialog
import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.ui.CellWithPaddingAndMargin
import org.thoughtcrime.securesms.ui.LocalDimensions
import org.thoughtcrime.securesms.ui.PreviewTheme
import org.thoughtcrime.securesms.ui.SessionShieldIcon
import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider
import org.thoughtcrime.securesms.ui.base
import org.thoughtcrime.securesms.ui.classicDarkColors
import org.thoughtcrime.securesms.ui.components.DestructiveButtons
import org.thoughtcrime.securesms.ui.components.OutlineButton
@ -58,7 +61,7 @@ class RecoveryPasswordActivity : BaseActionBarActivity() {
ComposeView(this).apply {
setContent {
RecoveryPassword(
RecoveryPasswordScreen(
viewModel.seed,
{ viewModel.copySeed(context) }
) { onHide() }
@ -93,27 +96,27 @@ class RecoveryPasswordActivity : BaseActionBarActivity() {
@Preview
@Composable
fun PreviewRecoveryPassword(
fun PreviewRecoveryPasswordScreen(
@PreviewParameter(ThemeResPreviewParameterProvider::class) themeResId: Int
) {
PreviewTheme(themeResId) {
RecoveryPassword(seed = "Voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane")
RecoveryPasswordScreen(seed = "Voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane")
}
}
@Composable
fun RecoveryPassword(
fun RecoveryPasswordScreen(
seed: String = "",
copySeed:() -> Unit = {},
onHide:() -> Unit = {}
) {
AppTheme {
Column(
verticalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(LocalDimensions.current.marginExtraSmall),
modifier = Modifier
.contentDescription(R.string.AccessibilityId_recovery_password)
.verticalScroll(rememberScrollState())
.padding(bottom = 16.dp)
.padding(bottom = LocalDimensions.current.marginExtraSmall)
) {
SmallButtons {
RecoveryPasswordCell(seed, copySeed)
@ -132,29 +135,17 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) {
CellWithPaddingAndMargin {
Column {
Row {
Text(stringResource(R.string.sessionRecoveryPassword))
Text(stringResource(R.string.sessionRecoveryPassword), style = MaterialTheme.typography.h8)
Spacer(Modifier.width(8.dp))
SessionShieldIcon()
}
Text(stringResource(R.string.recoveryPasswordDescription))
Spacer(modifier = Modifier.height(LocalDimensions.current.marginTiny))
Text(stringResource(R.string.recoveryPasswordDescription), style = MaterialTheme.typography.base)
AnimatedVisibility(!showQr) {
Text(
seed,
modifier = Modifier
.contentDescription(R.string.AccessibilityId_recovery_password_container)
.padding(vertical = 24.dp)
.border(
width = 1.dp,
color = classicDarkColors[3],
shape = RoundedCornerShape(11.dp)
)
.padding(24.dp),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.small.copy(fontFamily = FontFamily.Monospace),
color = MaterialTheme.colors.run { if (isLight) onSurface else secondary },
)
RecoveryPassword(seed)
}
AnimatedVisibility(
@ -163,7 +154,8 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) {
) {
QrImage(
seed,
modifier = Modifier.padding(vertical = 24.dp)
modifier = Modifier
.padding(vertical = 24.dp)
.contentDescription(R.string.AccessibilityId_qr_code),
icon = R.drawable.session_shield
)
@ -194,7 +186,26 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) {
}
@Composable
fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) {
private fun RecoveryPassword(seed: String) {
Text(
seed,
modifier = Modifier
.contentDescription(R.string.AccessibilityId_recovery_password_container)
.padding(vertical = 24.dp)
.border(
width = 1.dp,
color = classicDarkColors[3],
shape = RoundedCornerShape(11.dp)
)
.padding(24.dp),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.small.copy(fontFamily = FontFamily.Monospace),
color = MaterialTheme.colors.run { if (isLight) onSurface else secondary },
)
}
@Composable
private fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) {
CellWithPaddingAndMargin {
Row {
Column(

View File

@ -187,7 +187,7 @@ fun ItemButton(
) {
icon()
}
Text(text, modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.h8)
Text(text, modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.xl)
}
}

View File

@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.Dp
@ -43,7 +44,9 @@ data class Dimensions(
val itemSpacingSmall: Dp = 16.dp,
val itemSpacingMedium: Dp = 24.dp,
val marginTiny: Dp = 8.dp,
val marginSmall: Dp = 16.dp,
val marginExtraExtraSmall: Dp = 12.dp,
val marginExtraSmall: Dp = 16.dp,
val marginSmall: Dp = 24.dp,
val marginMedium: Dp = 32.dp,
val marginLarge: Dp = 64.dp,
val dividerIndent: Dp = 80.dp,
@ -65,7 +68,7 @@ fun AppTheme(
LocalCellColor to R.attr.colorSettingsBackground,
LocalButtonColor to R.attr.prominentButtonColor,
LocalLightCell to R.attr.lightCell,
LocalOnLightCell to R.attr.onLightCell
LocalOnLightCell to R.attr.onLightCell,
).map { (local, attr) -> local provides context.getColorFromTheme(attr) }.toTypedArray()
) {
AppCompatTheme(surface = surface) {
@ -134,12 +137,14 @@ val sessionTypography = Typography(
h6 = boldStyle(20.sp),
)
val Typography.medium get() = defaultStyle(18.sp)
val Typography.xl get() = defaultStyle(18.sp)
val Typography.large get() = defaultStyle(16.sp)
val Typography.base get() = defaultStyle(14.sp)
val Typography.baseBold get() = boldStyle(14.sp)
val Typography.baseMonospace get() = defaultStyle(14.sp).copy(fontFamily = FontFamily.Monospace)
val Typography.small get() = defaultStyle(12.sp)
val Typography.extraSmall get() = defaultStyle(11.sp)
val Typography.fine get() = defaultStyle(9.sp)
val Typography.h7 get() = boldStyle(18.sp)
val Typography.h8 get() = boldStyle(16.sp)

View File

@ -7,7 +7,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ButtonDefaults
@ -23,19 +22,19 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filter
import network.loki.messenger.R
import org.thoughtcrime.securesms.ui.GetString
import org.thoughtcrime.securesms.ui.LaunchedEffectAsync
import org.thoughtcrime.securesms.ui.LocalButtonColor
import org.thoughtcrime.securesms.ui.baseBold
import org.thoughtcrime.securesms.ui.colorDestructive
import org.thoughtcrime.securesms.ui.contentDescription
import org.thoughtcrime.securesms.ui.extraSmall
@ -59,7 +58,7 @@ fun OutlineButton(text: String, modifier: Modifier = Modifier, onClick: () -> Un
OutlineButton(
modifier.contentDescription(text),
onClick = onClick
) { Text(text) }
) { Text(text, style = MaterialTheme.typography.baseBold) }
}
@Composable
@ -129,13 +128,12 @@ fun FilledButton(
OutlinedButton(
modifier = modifier,
onClick = onClick,
shape = RoundedCornerShape(50),
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colors.background,
backgroundColor = LocalButtonColor.current
)
) {
Text(text = text)
Text(text = text, style = MaterialTheme.typography.baseBold)
}
}
@ -165,7 +163,6 @@ fun BorderlessButton(
TextButton(
onClick = onClick,
modifier = modifier.contentDescription(contentDescription),
shape = RoundedCornerShape(percent = 50),
colors = ButtonDefaults.outlinedButtonColors(
contentColor = contentColor,
backgroundColor = backgroundColor
@ -180,6 +177,31 @@ fun BorderlessButton(
}
}
@Composable
fun BorderlessHtmlButton(
textId: Int,
modifier: Modifier = Modifier,
contentColor: Color = MaterialTheme.colors.onBackground,
backgroundColor: Color = Color.Transparent,
onClick: () -> Unit
) {
TextButton(
onClick = onClick,
modifier = modifier,
colors = ButtonDefaults.outlinedButtonColors(
contentColor = contentColor,
backgroundColor = backgroundColor
)
) {
Text(
text = annotatedStringResource(textId),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.extraSmall,
modifier = Modifier.padding(horizontal = 2.dp)
)
}
}
private val MutableInteractionSource.releases
get() = interactions.filter { it is PressInteraction.Release }

View File

@ -0,0 +1,180 @@
package org.thoughtcrime.securesms.ui.components
import android.content.res.Resources
import android.graphics.Typeface
import android.text.Spanned
import android.text.SpannedString
import android.text.style.*
import android.util.Log
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.BaselineShift
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.core.text.HtmlCompat
// TODO Remove this file once we update to composeVersion=1.7.0-alpha06 fixes https://issuetracker.google.com/issues/139320238?pli=1
// which allows Stylized string in string resources
@Composable
@ReadOnlyComposable
private fun resources(): Resources {
LocalConfiguration.current
return LocalContext.current.resources
}
fun Spanned.toHtmlWithoutParagraphs(): String {
return HtmlCompat.toHtml(this, HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
.substringAfter("<p dir=\"ltr\">").substringBeforeLast("</p>")
}
fun Resources.getText(@StringRes id: Int, vararg args: Any): CharSequence {
val escapedArgs = args.map {
if (it is Spanned) it.toHtmlWithoutParagraphs() else it
}.toTypedArray()
val resource = SpannedString(getText(id))
val htmlResource = resource.toHtmlWithoutParagraphs()
val formattedHtml = String.format(htmlResource, *escapedArgs)
return HtmlCompat.fromHtml(formattedHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
@Composable
fun annotatedStringResource(@StringRes id: Int, vararg formatArgs: Any): AnnotatedString {
val resources = resources()
val density = LocalDensity.current
return remember(id, formatArgs) {
val text = resources.getText(id, *formatArgs)
spannableStringToAnnotatedString(text, density)
}
}
@Composable
fun annotatedStringResource(@StringRes id: Int): AnnotatedString {
val resources = resources()
val density = LocalDensity.current
return remember(id) {
val text = resources.getText(id)
spannableStringToAnnotatedString(text, density)
}
}
private fun spannableStringToAnnotatedString(
text: CharSequence,
density: Density
): AnnotatedString {
return if (text is Spanned) {
with(density) {
buildAnnotatedString {
append((text.toString()))
text.getSpans(0, text.length, Any::class.java).forEach {
val start = text.getSpanStart(it)
val end = text.getSpanEnd(it)
when (it) {
is StyleSpan -> when (it.style) {
Typeface.NORMAL -> addStyle(
SpanStyle(
fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Normal
),
start,
end
)
Typeface.BOLD -> addStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Normal
),
start,
end
)
Typeface.ITALIC -> addStyle(
SpanStyle(
fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Italic
),
start,
end
)
Typeface.BOLD_ITALIC -> addStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Italic
),
start,
end
)
}
is TypefaceSpan -> addStyle(
SpanStyle(
fontFamily = when (it.family) {
FontFamily.SansSerif.name -> FontFamily.SansSerif
FontFamily.Serif.name -> FontFamily.Serif
FontFamily.Monospace.name -> FontFamily.Monospace
FontFamily.Cursive.name -> FontFamily.Cursive
else -> FontFamily.Default
}
),
start,
end
)
is BulletSpan -> {
Log.d("StringResources", "BulletSpan not supported yet")
addStyle(SpanStyle(), start, end)
}
is AbsoluteSizeSpan -> addStyle(
SpanStyle(fontSize = if (it.dip) it.size.dp.toSp() else it.size.toSp()),
start,
end
)
is RelativeSizeSpan -> addStyle(
SpanStyle(fontSize = it.sizeChange.em),
start,
end
)
is StrikethroughSpan -> addStyle(
SpanStyle(textDecoration = TextDecoration.LineThrough),
start,
end
)
is UnderlineSpan -> addStyle(
SpanStyle(textDecoration = TextDecoration.Underline),
start,
end
)
is SuperscriptSpan -> addStyle(
SpanStyle(baselineShift = BaselineShift.Superscript),
start,
end
)
is SubscriptSpan -> addStyle(
SpanStyle(baselineShift = BaselineShift.Subscript),
start,
end
)
is ForegroundColorSpan -> addStyle(
SpanStyle(color = Color(it.foregroundColor)),
start,
end
)
else -> addStyle(SpanStyle(), start, end)
}
}
}
}
} else {
AnnotatedString(text.toString())
}
}

View File

@ -22,6 +22,7 @@ import network.loki.messenger.R
import org.thoughtcrime.securesms.ui.LocalButtonColor
import org.thoughtcrime.securesms.ui.PreviewTheme
import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider
import org.thoughtcrime.securesms.ui.h8
private val TITLES = listOf(R.string.sessionRecoveryPassword, R.string.qrScan)
@ -45,7 +46,10 @@ fun SessionTabRow(pagerState: PagerState, titles: List<Int>) {
selectedContentColor = MaterialTheme.colors.onPrimary,
unselectedContentColor = MaterialTheme.colors.onPrimary,
) {
Text(stringResource(id = it))
Text(
stringResource(id = it),
style = MaterialTheme.typography.h8
)
}
}
}

View File

@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.thoughtcrime.securesms.ui.base
import org.thoughtcrime.securesms.ui.baseBold
import org.thoughtcrime.securesms.ui.outlinedTextFieldColors
@ -28,8 +29,14 @@ fun SessionOutlinedTextField(
OutlinedTextField(
value = text,
modifier = Modifier.fillMaxWidth(),
textStyle = MaterialTheme.typography.base,
onValueChange = { onChange(it) },
placeholder = { Text(placeholder) },
placeholder = {
Text(
placeholder,
style = MaterialTheme.typography.base
)
},
colors = outlinedTextFieldColors(error != null),
singleLine = true,
keyboardActions = KeyboardActions(

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
<path
android:pathData="M6,10.56C8.497,10.56 10.559,8.495 10.559,6.002C10.559,3.504 8.494,1.443 5.996,1.443C3.503,1.443 1.441,3.504 1.441,6.002C1.441,8.495 3.507,10.56 6,10.56ZM6,9.662C3.968,9.662 2.343,8.033 2.343,6.002C2.343,3.97 3.965,2.341 5.996,2.341C8.027,2.341 9.661,3.97 9.661,6.002C9.661,8.033 8.031,9.662 6,9.662Z"
android:fillColor="#A1A2A1"/>
<path
android:pathData="M6.262,5.758C6.436,5.758 6.523,5.712 6.648,5.592C6.759,5.464 6.807,5.337 6.811,5.125L6.81,5.095C6.809,4.98 6.798,4.907 6.759,4.802C6.718,4.703 6.68,4.632 6.609,4.557C6.535,4.48 6.467,4.426 6.362,4.384C6.258,4.337 6.152,4.313 6.024,4.313C5.743,4.317 5.575,4.386 5.413,4.55C5.261,4.721 5.192,4.907 5.19,5.183L5.192,5.484L4.582,5.485V5.151C4.582,4.973 4.609,4.791 4.667,4.628C4.729,4.466 4.826,4.295 4.942,4.171C5.058,4.047 5.227,3.928 5.401,3.855C5.576,3.781 5.803,3.738 6.031,3.738C6.225,3.738 6.43,3.776 6.593,3.842C6.755,3.908 6.908,4.004 7.024,4.12C7.14,4.233 7.252,4.392 7.318,4.543C7.383,4.69 7.419,4.87 7.419,5.036L7.418,5.149C7.418,5.3 7.389,5.459 7.335,5.598C7.284,5.733 7.201,5.868 7.109,5.969C7.016,6.07 6.898,6.162 6.77,6.224C6.646,6.282 6.476,6.327 6.324,6.322L6.244,6.32C6.174,6.325 6.144,6.341 6.143,6.437L6.142,6.928L5.557,6.926V6.315C5.557,6.168 5.605,6.021 5.704,5.926C5.793,5.821 5.959,5.755 6.116,5.758H6.262Z"
android:fillColor="#A1A2A1"/>
<path
android:pathData="M6.325,7.62C6.325,7.879 6.116,8.088 5.857,8.088C5.599,8.088 5.389,7.879 5.389,7.62C5.389,7.362 5.599,7.152 5.857,7.152C6.116,7.152 6.325,7.362 6.325,7.62Z"
android:fillColor="#A1A2A1"/>
</vector>

View File

@ -1067,7 +1067,7 @@
<string name="onboardingBubbleCreatingAnAccountIsEasy">Creating an account is \ninstant, free, and \nanonymous 👇</string>
<string name="onboardingAccountCreate">Create account</string>
<string name="onboardingAccountExists">I have an account</string>
<string name="onboardingTosPrivacy">By using this service, you agree to our Terms of Service and Privacy Policy</string>
<string name="onboardingTosPrivacy">By using this service, you agree to our <b>Terms of Service</b> and <b>Privacy Policy</b></string>
<string name="qrNotRecoveryPassword">This QR code does not contain a Recovery Password.</string>
@ -1091,7 +1091,7 @@
<string name="recoveryPasswordHidePermanently">Hide Recovery Password Permanently</string>
<string name="recoveryPasswordHidePermanentlyDescription1"><![CDATA[Without your recovery password, you cannot load your account on new devices. <br /><br />We strongly recommend you save your recovery password in a safe and secure place before continuing.]]></string>
<string name="recoveryPasswordHidePermanentlyDescription2">Are you sure you want to permanently hide your recovery password on this device? This cannot be undone.</string>
<string name="recoveryPasswordDescription">Use your recovery password to load your account on new devices. Your account cannot be recovered without your recovery password. Make sure it\'s stored somewhere safe and secure — and don\'t share it with anyone.</string>
<string name="recoveryPasswordDescription">Use your recovery password to load your account on new devices.\n\nYour account cannot be recovered without your recovery password. Make sure it\'s stored somewhere safe and secure — and don\'t share it with anyone.</string>
<string name="hide">Hide</string>
<string name="recoveryPasswordHideRecoveryPassword">Hide Recovery Password</string>
<string name="qrView">View QR</string>