Add username link share sheet.
This commit is contained in:
parent
5698e0deda
commit
96333b616b
8 changed files with 242 additions and 28 deletions
|
@ -42,7 +42,9 @@ abstract class FixedRoundedCornerBottomSheetDialogFragment : BottomSheetDialogFr
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
WindowUtil.initializeScreenshotSecurity(requireContext(), dialog!!.window!!)
|
dialog?.window?.let { window ->
|
||||||
|
WindowUtil.initializeScreenshotSecurity(requireContext(), window)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
|
|
@ -51,7 +51,7 @@ fun QrCodeBadge(
|
||||||
username: String,
|
username: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
usernameCopyable: Boolean = false,
|
usernameCopyable: Boolean = false,
|
||||||
onClick: (() -> Unit) = {}
|
onClick: ((String) -> Unit) = {}
|
||||||
) {
|
) {
|
||||||
val borderColor by animateColorAsState(targetValue = colorScheme.borderColor, label = "border")
|
val borderColor by animateColorAsState(targetValue = colorScheme.borderColor, label = "border")
|
||||||
val foregroundColor by animateColorAsState(targetValue = colorScheme.foregroundColor, label = "foreground")
|
val foregroundColor by animateColorAsState(targetValue = colorScheme.foregroundColor, label = "foreground")
|
||||||
|
@ -132,7 +132,7 @@ fun QrCodeBadge(
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.clickable(
|
.clickable(
|
||||||
enabled = usernameCopyable,
|
enabled = usernameCopyable,
|
||||||
onClick = onClick
|
onClick = { onClick(username) }
|
||||||
)
|
)
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
@ -43,6 +44,7 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.app.ShareCompat
|
import androidx.core.app.ShareCompat
|
||||||
|
import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
@ -59,19 +61,24 @@ import org.signal.core.util.concurrent.LifecycleDisposable
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.components.settings.app.usernamelinks.main.UsernameLinkSettingsState.ActiveTab
|
import org.thoughtcrime.securesms.components.settings.app.usernamelinks.main.UsernameLinkSettingsState.ActiveTab
|
||||||
import org.thoughtcrime.securesms.compose.ComposeFragment
|
import org.thoughtcrime.securesms.compose.ComposeFragment
|
||||||
import org.thoughtcrime.securesms.compose.ScreenshotController
|
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider
|
import org.thoughtcrime.securesms.providers.BlobProvider
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
@OptIn(
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
ExperimentalPermissionsApi::class
|
|
||||||
)
|
|
||||||
class UsernameLinkSettingsFragment : ComposeFragment() {
|
class UsernameLinkSettingsFragment : ComposeFragment() {
|
||||||
|
|
||||||
private val viewModel: UsernameLinkSettingsViewModel by viewModels()
|
private val viewModel: UsernameLinkSettingsViewModel by viewModels()
|
||||||
private val disposables: LifecycleDisposable = LifecycleDisposable()
|
private val disposables: LifecycleDisposable = LifecycleDisposable()
|
||||||
|
|
||||||
private val screenshotController = ScreenshotController()
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
setFragmentResultListener(UsernameLinkShareBottomSheet.REQUEST_KEY) { key, bundle ->
|
||||||
|
if (bundle.getBoolean(UsernameLinkShareBottomSheet.KEY_COPY)) {
|
||||||
|
viewModel.onLinkCopied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -83,6 +90,15 @@ class UsernameLinkSettingsFragment : ComposeFragment() {
|
||||||
var showResetDialog: Boolean by remember { mutableStateOf(false) }
|
var showResetDialog: Boolean by remember { mutableStateOf(false) }
|
||||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||||
val cameraPermissionState: PermissionState = rememberPermissionState(permission = android.Manifest.permission.CAMERA)
|
val cameraPermissionState: PermissionState = rememberPermissionState(permission = android.Manifest.permission.CAMERA)
|
||||||
|
val linkCopiedEvent: UUID? by viewModel.linkCopiedEvent
|
||||||
|
|
||||||
|
val linkCopiedString = stringResource(R.string.UsernameLinkSettings_link_copied_toast)
|
||||||
|
|
||||||
|
LaunchedEffect(linkCopiedEvent) {
|
||||||
|
if (linkCopiedEvent != null) {
|
||||||
|
snackbarHostState.showSnackbar(linkCopiedString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.graphics.Rect
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
|
@ -39,6 +40,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.NetworkUtil
|
import org.thoughtcrime.securesms.util.NetworkUtil
|
||||||
import org.whispersystems.signalservice.api.push.UsernameLinkComponents
|
import org.whispersystems.signalservice.api.push.UsernameLinkComponents
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
class UsernameLinkSettingsViewModel : ViewModel() {
|
class UsernameLinkSettingsViewModel : ViewModel() {
|
||||||
|
|
||||||
|
@ -58,6 +60,9 @@ class UsernameLinkSettingsViewModel : ViewModel() {
|
||||||
private val disposable: CompositeDisposable = CompositeDisposable()
|
private val disposable: CompositeDisposable = CompositeDisposable()
|
||||||
private val usernameLink: BehaviorSubject<Optional<UsernameLinkComponents>> = BehaviorSubject.createDefault(Optional.ofNullable(SignalStore.account().usernameLink))
|
private val usernameLink: BehaviorSubject<Optional<UsernameLinkComponents>> = BehaviorSubject.createDefault(Optional.ofNullable(SignalStore.account().usernameLink))
|
||||||
|
|
||||||
|
private val _linkCopiedEvent: MutableState<UUID?> = mutableStateOf(null)
|
||||||
|
val linkCopiedEvent: State<UUID?> get() = _linkCopiedEvent
|
||||||
|
|
||||||
init {
|
init {
|
||||||
disposable += usernameLink
|
disposable += usernameLink
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
|
@ -177,6 +182,10 @@ class UsernameLinkSettingsViewModel : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onLinkCopied() {
|
||||||
|
_linkCopiedEvent.value = UUID.randomUUID()
|
||||||
|
}
|
||||||
|
|
||||||
private fun generateQrCodeData(url: Optional<String>): Single<Optional<QrCodeData>> {
|
private fun generateQrCodeData(url: Optional<String>): Single<Optional<QrCodeData>> {
|
||||||
return Single.fromCallable {
|
return Single.fromCallable {
|
||||||
url.map { QrCodeData.forData(it, 64) }
|
url.map { QrCodeData.forData(it, 64) }
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.thoughtcrime.securesms.components.settings.app.usernamelinks.main
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.SnackbarHostState
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.fragment.app.setFragmentResult
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import org.signal.core.ui.BottomSheets
|
||||||
|
import org.signal.core.ui.theme.SignalTheme
|
||||||
|
import org.thoughtcrime.securesms.R
|
||||||
|
import org.thoughtcrime.securesms.components.webrtc.requests.CallLinkIncomingRequestSheet
|
||||||
|
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||||
|
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||||
|
import org.thoughtcrime.securesms.profiles.manage.UsernameRepository.toLink
|
||||||
|
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||||
|
import org.thoughtcrime.securesms.util.Util
|
||||||
|
|
||||||
|
class UsernameLinkShareBottomSheet : ComposeBottomSheetDialogFragment() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val REQUEST_KEY = "link_share_bottom_sheet"
|
||||||
|
const val KEY_COPY = "copy"
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun show(fragmentManager: FragmentManager) {
|
||||||
|
CallLinkIncomingRequestSheet().show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun SheetContent() {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
|
Content(
|
||||||
|
usernameLink = SignalStore.account().usernameLink?.toLink() ?: "",
|
||||||
|
scope = scope,
|
||||||
|
snackbarHostState = snackbarHostState,
|
||||||
|
dismissDialog = { didCopy ->
|
||||||
|
setFragmentResult(REQUEST_KEY, bundleOf(KEY_COPY to didCopy))
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Content(
|
||||||
|
usernameLink: String,
|
||||||
|
scope: CoroutineScope,
|
||||||
|
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
|
||||||
|
dismissDialog: (Boolean) -> Unit = {}
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val usernameCopiedString = stringResource(id = R.string.UsernameLinkSettings_username_copied_toast)
|
||||||
|
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
BottomSheets.Handle()
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.UsernameLinkShareBottomSheet_title),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 41.dp, vertical = 24.dp)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = usernameLink,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 24.dp)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f),
|
||||||
|
shape = RoundedCornerShape(12.dp)
|
||||||
|
)
|
||||||
|
.padding(all = 16.dp)
|
||||||
|
)
|
||||||
|
ButtonRow(
|
||||||
|
icon = painterResource(R.drawable.symbol_copy_android_24),
|
||||||
|
text = stringResource(R.string.UsernameLinkShareBottomSheet_copy_link),
|
||||||
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
|
onClick = {
|
||||||
|
Util.copyToClipboard(context, usernameLink)
|
||||||
|
dismissDialog(true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
ButtonRow(
|
||||||
|
icon = painterResource(R.drawable.symbol_share_android_24),
|
||||||
|
text = stringResource(R.string.UsernameLinkShareBottomSheet_share),
|
||||||
|
modifier = Modifier.padding(bottom = 12.dp),
|
||||||
|
onClick = {
|
||||||
|
dismissDialog(false)
|
||||||
|
|
||||||
|
val sendIntent: Intent = Intent().apply {
|
||||||
|
action = Intent.ACTION_SEND
|
||||||
|
type = "text/plain"
|
||||||
|
putExtra(Intent.EXTRA_TEXT, usernameLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
context.startActivity(Intent.createChooser(sendIntent, null))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ButtonRow(icon: Painter, text: String, modifier: Modifier = Modifier, onClick: () -> Unit = {}) {
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onClick() }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = icon,
|
||||||
|
contentDescription = text,
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 24.dp, vertical = 16.dp)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(vertical = 16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(name = "Light Theme", group = "content", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
@Preview(name = "Dark Theme", group = "content", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
@Composable
|
||||||
|
private fun ContentPreview() {
|
||||||
|
SignalTheme {
|
||||||
|
Surface {
|
||||||
|
Content(
|
||||||
|
usernameLink = "https://signal.me#eufzLWmFFUYAOqnVJ4Zlt0KqXf87r59FC1hZ3r7WipjKvgzMBg7DBlY5DB5hQTjsw0",
|
||||||
|
scope = rememberCoroutineScope()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(name = "Light Theme", group = "button row", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
@Preview(name = "Dark Theme", group = "button row", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
@Composable
|
||||||
|
private fun ButtonRowPreview() {
|
||||||
|
SignalTheme {
|
||||||
|
Surface {
|
||||||
|
ButtonRow(icon = painterResource(R.drawable.symbol_share_android_24), text = "Share")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,8 @@ fun UsernameLinkShareScreen(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onResetClicked: () -> Unit
|
onResetClicked: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
when (state.usernameLinkResetResult) {
|
when (state.usernameLinkResetResult) {
|
||||||
UsernameLinkResetResult.NetworkUnavailable -> {
|
UsernameLinkResetResult.NetworkUnavailable -> {
|
||||||
ResetLinkResultDialog(stringResource(R.string.UsernameLinkSettings_reset_link_result_network_unavailable), onDismiss = onLinkResultHandled)
|
ResetLinkResultDialog(stringResource(R.string.UsernameLinkSettings_reset_link_result_network_unavailable), onDismiss = onLinkResultHandled)
|
||||||
|
@ -81,7 +83,8 @@ fun UsernameLinkShareScreen(
|
||||||
username = state.username,
|
username = state.username,
|
||||||
usernameCopyable = true,
|
usernameCopyable = true,
|
||||||
modifier = Modifier.padding(horizontal = 58.dp, vertical = 24.dp),
|
modifier = Modifier.padding(horizontal = 58.dp, vertical = 24.dp),
|
||||||
onClick = {
|
onClick = { username ->
|
||||||
|
Util.copyToClipboard(context, username)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
snackbarHostState.showSnackbar(usernameCopiedString)
|
snackbarHostState.showSnackbar(usernameCopiedString)
|
||||||
}
|
}
|
||||||
|
@ -95,8 +98,9 @@ fun UsernameLinkShareScreen(
|
||||||
|
|
||||||
LinkRow(
|
LinkRow(
|
||||||
linkState = state.usernameLinkState,
|
linkState = state.usernameLinkState,
|
||||||
snackbarHostState = snackbarHostState,
|
onClick = {
|
||||||
scope = scope
|
navController.safeNavigate(UsernameLinkSettingsFragmentDirections.actionUsernameLinkSettingsFragmentToUsernameLinkShareBottomSheet())
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
@ -142,9 +146,7 @@ private fun ButtonBar(onShareClicked: () -> Unit, onColorClicked: () -> Unit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun LinkRow(linkState: UsernameLinkState, snackbarHostState: SnackbarHostState, scope: CoroutineScope) {
|
private fun LinkRow(linkState: UsernameLinkState, onClick: () -> Unit = {}) {
|
||||||
val context = LocalContext.current
|
|
||||||
val copyMessage = stringResource(R.string.UsernameLinkSettings_link_copied_toast)
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
@ -161,11 +163,7 @@ private fun LinkRow(linkState: UsernameLinkState, snackbarHostState: SnackbarHos
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
)
|
)
|
||||||
.clickable(enabled = linkState is UsernameLinkState.Present) {
|
.clickable(enabled = linkState is UsernameLinkState.Present) {
|
||||||
Util.copyToClipboard(context, (linkState as UsernameLinkState.Present).link)
|
onClick()
|
||||||
|
|
||||||
scope.launch {
|
|
||||||
snackbarHostState.showSnackbar(copyMessage)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.padding(horizontal = 26.dp, vertical = 16.dp)
|
.padding(horizontal = 26.dp, vertical = 16.dp)
|
||||||
.alpha(if (linkState is UsernameLinkState.Present) 1.0f else 0.6f)
|
.alpha(if (linkState is UsernameLinkState.Present) 1.0f else 0.6f)
|
||||||
|
@ -225,19 +223,13 @@ private fun LinkRowPreview() {
|
||||||
Surface {
|
Surface {
|
||||||
Column(modifier = Modifier.padding(8.dp)) {
|
Column(modifier = Modifier.padding(8.dp)) {
|
||||||
LinkRow(
|
LinkRow(
|
||||||
linkState = UsernameLinkState.Present("https://signal.me/#eu/asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf"),
|
linkState = UsernameLinkState.Present("https://signal.me/#eu/asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf")
|
||||||
snackbarHostState = SnackbarHostState(),
|
|
||||||
scope = rememberCoroutineScope()
|
|
||||||
)
|
)
|
||||||
LinkRow(
|
LinkRow(
|
||||||
linkState = UsernameLinkState.NotSet,
|
linkState = UsernameLinkState.NotSet
|
||||||
snackbarHostState = SnackbarHostState(),
|
|
||||||
scope = rememberCoroutineScope()
|
|
||||||
)
|
)
|
||||||
LinkRow(
|
LinkRow(
|
||||||
linkState = UsernameLinkState.Resetting,
|
linkState = UsernameLinkState.Resetting
|
||||||
snackbarHostState = SnackbarHostState(),
|
|
||||||
scope = rememberCoroutineScope()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,18 @@
|
||||||
app:exitAnim="@anim/fragment_open_exit"
|
app:exitAnim="@anim/fragment_open_exit"
|
||||||
app:popEnterAnim="@anim/fragment_close_enter"
|
app:popEnterAnim="@anim/fragment_close_enter"
|
||||||
app:popExitAnim="@anim/fragment_close_exit" />
|
app:popExitAnim="@anim/fragment_close_exit" />
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_usernameLinkSettingsFragment_to_usernameLinkShareBottomSheet"
|
||||||
|
app:destination="@id/usernameLinkShareBottomSheet" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/usernameLinkQrColorPickerFragment"
|
android:id="@+id/usernameLinkQrColorPickerFragment"
|
||||||
android:name="org.thoughtcrime.securesms.components.settings.app.usernamelinks.colorpicker.UsernameLinkQrColorPickerFragment" />
|
android:name="org.thoughtcrime.securesms.components.settings.app.usernamelinks.colorpicker.UsernameLinkQrColorPickerFragment" />
|
||||||
|
|
||||||
|
<dialog
|
||||||
|
android:id="@+id/usernameLinkShareBottomSheet"
|
||||||
|
android:name="org.thoughtcrime.securesms.components.settings.app.usernamelinks.main.UsernameLinkShareBottomSheet" />
|
||||||
|
|
||||||
</navigation>
|
</navigation>
|
|
@ -6401,6 +6401,13 @@
|
||||||
<!-- Body of a dialog that is displayed when we failed to reset your username link because of a transient network issue. -->
|
<!-- Body of a dialog that is displayed when we failed to reset your username link because of a transient network issue. -->
|
||||||
<string name="UsernameLinkSettings_reset_link_result_network_error">A network error occurred while trying to reset your link. Try again later.</string>
|
<string name="UsernameLinkSettings_reset_link_result_network_error">A network error occurred while trying to reset your link. Try again later.</string>
|
||||||
|
|
||||||
|
<!-- Explanatory text at the top of a bottom sheet describing how username links work -->
|
||||||
|
<string name="UsernameLinkShareBottomSheet_title">Anyone with this link can view your username and start a chat with you. Only share it with people you trust.</string>
|
||||||
|
<!-- A button label for a button that, when pressed, will copy your username link to the clipboard -->
|
||||||
|
<string name="UsernameLinkShareBottomSheet_copy_link">Copy link</string>
|
||||||
|
<!-- A button label for a button that, when pressed, will open a share sheet for sharing your username link -->
|
||||||
|
<string name="UsernameLinkShareBottomSheet_share">Share</string>
|
||||||
|
|
||||||
<!-- PendingParticipantsView -->
|
<!-- PendingParticipantsView -->
|
||||||
<!-- Displayed in the popup card when a remote user attempts to join a call link -->
|
<!-- Displayed in the popup card when a remote user attempts to join a call link -->
|
||||||
<string name="PendingParticipantsView__would_like_to_join">Would like to join…</string>
|
<string name="PendingParticipantsView__would_like_to_join">Would like to join…</string>
|
||||||
|
|
Loading…
Add table
Reference in a new issue