Add call link details screen scaffolding.

This commit is contained in:
Alex Hart
2023-04-21 10:48:42 -03:00
parent 5f7414e84c
commit bff8fc8230
14 changed files with 371 additions and 46 deletions
@@ -0,0 +1,8 @@
package org.thoughtcrime.securesms.calls.links
/**
* Utility object for call links to try to keep some common logic in one place.
*/
object CallLinks {
fun url(identifier: String) = "https://calls.signal.org/#$identifier"
}
@@ -28,18 +28,21 @@ import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
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.fragment.app.viewModels import androidx.core.os.bundleOf
import androidx.fragment.app.setFragmentResult
import androidx.navigation.fragment.navArgs
import org.signal.core.ui.Buttons import org.signal.core.ui.Buttons
import org.signal.core.ui.Scaffolds import org.signal.core.ui.Scaffolds
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.calls.links.create.CreateCallLinkViewModel
import org.thoughtcrime.securesms.compose.ComposeDialogFragment import org.thoughtcrime.securesms.compose.ComposeDialogFragment
class EditCallLinkNameDialogFragment : ComposeDialogFragment() { class EditCallLinkNameDialogFragment : ComposeDialogFragment() {
private val viewModel: CreateCallLinkViewModel by viewModels( companion object {
ownerProducer = { requireParentFragment() } const val RESULT_KEY = "edit_call_link_name"
) }
private val args: EditCallLinkNameDialogFragmentArgs by navArgs()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -57,12 +60,11 @@ class EditCallLinkNameDialogFragment : ComposeDialogFragment() {
@Preview @Preview
@Composable @Composable
override fun DialogContent() { override fun DialogContent() {
val viewModelCallName by viewModel.callName
var callName by remember { var callName by remember {
mutableStateOf( mutableStateOf(
TextFieldValue( TextFieldValue(
text = viewModelCallName, text = args.name,
selection = TextRange(viewModelCallName.length) selection = TextRange(args.name.length)
) )
) )
} }
@@ -97,7 +99,7 @@ class EditCallLinkNameDialogFragment : ComposeDialogFragment() {
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
Buttons.MediumTonal( Buttons.MediumTonal(
onClick = { onClick = {
viewModel.setCallName(callName.text) setFragmentResult(RESULT_KEY, bundleOf(RESULT_KEY to callName.text))
dismiss() dismiss()
}, },
modifier = Modifier.align(End) modifier = Modifier.align(End)
@@ -15,12 +15,14 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
@@ -29,14 +31,25 @@ import androidx.compose.ui.unit.dp
import org.signal.core.ui.Buttons import org.signal.core.ui.Buttons
import org.signal.core.ui.theme.SignalTheme import org.signal.core.ui.theme.SignalTheme
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.conversation.colors.AvatarColorPair
import org.thoughtcrime.securesms.database.CallLinkTable
@Preview @Preview
@Composable @Composable
private fun SignalCallRowPreview() { private fun SignalCallRowPreview() {
val avatarColor = remember { AvatarColor.random() }
val callLink = remember {
CallLinkTable.CallLink(
name = "Call Name",
identifier = "blahblahblah",
avatarColor = avatarColor,
isApprovalRequired = false
)
}
SignalTheme(false) { SignalTheme(false) {
SignalCallRow( SignalCallRow(
callName = "Call Name", callLink = callLink,
callLink = "https://call.signal.org#blahblahblah",
onJoinClicked = {} onJoinClicked = {}
) )
} }
@@ -44,8 +57,7 @@ private fun SignalCallRowPreview() {
@Composable @Composable
fun SignalCallRow( fun SignalCallRow(
callName: String, callLink: CallLinkTable.CallLink,
callLink: String,
onJoinClicked: () -> Unit, onJoinClicked: () -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
@@ -60,15 +72,17 @@ fun SignalCallRow(
) )
.padding(16.dp) .padding(16.dp)
) { ) {
val callColorPair = AvatarColorPair.create(LocalContext.current, callLink.avatarColor)
Image( Image(
imageVector = ImageVector.vectorResource(id = R.drawable.symbol_video_display_bold_40), imageVector = ImageVector.vectorResource(id = R.drawable.symbol_video_display_bold_40),
contentScale = ContentScale.Inside, contentScale = ContentScale.Inside,
contentDescription = null, contentDescription = null,
colorFilter = ColorFilter.tint(Color(0xFF5151F6)), colorFilter = ColorFilter.tint(Color(callColorPair.foregroundColor)),
modifier = Modifier modifier = Modifier
.size(64.dp) .size(64.dp)
.background( .background(
color = Color(0xFFE5E5FE), color = Color(callColorPair.backgroundColor),
shape = CircleShape shape = CircleShape
) )
) )
@@ -81,10 +95,10 @@ fun SignalCallRow(
.align(CenterVertically) .align(CenterVertically)
) { ) {
Text( Text(
text = callName.ifEmpty { stringResource(id = R.string.CreateCallLinkBottomSheetDialogFragment__signal_call) } text = callLink.name.ifEmpty { stringResource(id = R.string.CreateCallLinkBottomSheetDialogFragment__signal_call) }
) )
Text( Text(
text = callLink, text = CallLinks.url(callLink.identifier),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant color = MaterialTheme.colorScheme.onSurfaceVariant
) )
@@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.calls.links.create
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Intent import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -25,15 +27,18 @@ import androidx.compose.ui.text.style.TextAlign
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.viewModels import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import org.signal.core.ui.Buttons import org.signal.core.ui.Buttons
import org.signal.core.ui.Dividers import org.signal.core.ui.Dividers
import org.signal.core.ui.Rows import org.signal.core.ui.Rows
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.calls.links.CallLinks
import org.thoughtcrime.securesms.calls.links.EditCallLinkNameDialogFragment import org.thoughtcrime.securesms.calls.links.EditCallLinkNameDialogFragment
import org.thoughtcrime.securesms.calls.links.SignalCallRow import org.thoughtcrime.securesms.calls.links.SignalCallRow
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragment import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragment
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragmentArgs import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragmentArgs
import org.thoughtcrime.securesms.database.CallLinkTable
import org.thoughtcrime.securesms.sharing.MultiShareArgs import org.thoughtcrime.securesms.sharing.MultiShareArgs
import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.Util
@@ -46,6 +51,14 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
override val peekHeightPercentage: Float = 1f override val peekHeightPercentage: Float = 1f
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
parentFragmentManager.setFragmentResultListener(EditCallLinkNameDialogFragment.RESULT_KEY, viewLifecycleOwner) { resultKey, bundle ->
if (bundle.containsKey(resultKey)) {
viewModel.setCallName(bundle.getString(resultKey)!!)
}
}
}
@Composable @Composable
override fun SheetContent() { override fun SheetContent() {
Column( Column(
@@ -53,9 +66,7 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
.fillMaxWidth() .fillMaxWidth()
.wrapContentSize(Alignment.Center) .wrapContentSize(Alignment.Center)
) { ) {
val callName: String by viewModel.callName val callLink: CallLinkTable.CallLink by viewModel.callLink
val callLink: String by viewModel.callLink
val approveAllMembers: Boolean by viewModel.approveAllMembers
Handle(modifier = Modifier.align(Alignment.CenterHorizontally)) Handle(modifier = Modifier.align(Alignment.CenterHorizontally))
@@ -71,7 +82,6 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
SignalCallRow( SignalCallRow(
callName = callName,
callLink = callLink, callLink = callLink,
onJoinClicked = this@CreateCallLinkBottomSheetDialogFragment::onJoinClicked onJoinClicked = this@CreateCallLinkBottomSheetDialogFragment::onJoinClicked
) )
@@ -84,7 +94,7 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
) )
Rows.ToggleRow( Rows.ToggleRow(
checked = approveAllMembers, checked = callLink.isApprovalRequired,
text = stringResource(id = R.string.CreateCallLinkBottomSheetDialogFragment__approve_all_members), text = stringResource(id = R.string.CreateCallLinkBottomSheetDialogFragment__approve_all_members),
onCheckChanged = viewModel::setApproveAllMembers, onCheckChanged = viewModel::setApproveAllMembers,
modifier = Modifier.clickable(onClick = viewModel::toggleApproveAllMembers) modifier = Modifier.clickable(onClick = viewModel::toggleApproveAllMembers)
@@ -124,7 +134,10 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
} }
private fun onAddACallNameClicked() { private fun onAddACallNameClicked() {
EditCallLinkNameDialogFragment().show(childFragmentManager, null) val snapshot = viewModel.callLink.value
findNavController().navigate(
CreateCallLinkBottomSheetDialogFragmentDirections.actionCreateCallLinkBottomSheetToEditCallLinkNameDialogFragment(snapshot.name)
)
} }
private fun onJoinClicked() { private fun onJoinClicked() {
@@ -142,7 +155,7 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
canSendToNonPush = false, canSendToNonPush = false,
multiShareArgs = listOf( multiShareArgs = listOf(
MultiShareArgs.Builder() MultiShareArgs.Builder()
.withDraftText(snapshot) .withDraftText(snapshot.identifier)
.build() .build()
) )
) )
@@ -151,7 +164,7 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
private fun onCopyLinkClicked() { private fun onCopyLinkClicked() {
val snapshot = viewModel.callLink.value val snapshot = viewModel.callLink.value
Util.copyToClipboard(requireContext(), snapshot) Util.copyToClipboard(requireContext(), CallLinks.url(snapshot.identifier))
Toast.makeText(requireContext(), R.string.CreateCallLinkBottomSheetDialogFragment__copied_to_clipboard, Toast.LENGTH_LONG).show() Toast.makeText(requireContext(), R.string.CreateCallLinkBottomSheetDialogFragment__copied_to_clipboard, Toast.LENGTH_LONG).show()
} }
@@ -159,7 +172,7 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
val snapshot = viewModel.callLink.value val snapshot = viewModel.callLink.value
val mimeType = Intent.normalizeMimeType("text/plain") val mimeType = Intent.normalizeMimeType("text/plain")
val shareIntent = ShareCompat.IntentBuilder(requireContext()) val shareIntent = ShareCompat.IntentBuilder(requireContext())
.setText(snapshot) .setText(CallLinks.url(snapshot.identifier))
.setType(mimeType) .setType(mimeType)
.createChooserIntent() .createChooserIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
@@ -4,29 +4,24 @@ 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.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.database.CallLinkTable
class CreateCallLinkViewModel : ViewModel() { class CreateCallLinkViewModel : ViewModel() {
private val _callName: MutableState<String> = mutableStateOf("") private val _callLink: MutableState<CallLinkTable.CallLink> = mutableStateOf(
private val _callLink: MutableState<String> = mutableStateOf("") CallLinkTable.CallLink("", "", AvatarColor.random(), false)
private val _approveAllMembers: MutableState<Boolean> = mutableStateOf(false) )
val callLink: State<CallLinkTable.CallLink> = _callLink
val callName: State<String> = _callName
val callLink: State<String> = _callLink
val approveAllMembers: State<Boolean> = _approveAllMembers
fun setApproveAllMembers(approveAllMembers: Boolean) { fun setApproveAllMembers(approveAllMembers: Boolean) {
_approveAllMembers.value = approveAllMembers _callLink.value = _callLink.value.copy(isApprovalRequired = approveAllMembers)
} }
fun toggleApproveAllMembers() { fun toggleApproveAllMembers() {
_approveAllMembers.value = !_approveAllMembers.value _callLink.value = _callLink.value.copy(isApprovalRequired = _callLink.value.isApprovalRequired)
} }
fun setCallName(callName: String) { fun setCallName(callName: String) {
_callName.value = callName _callLink.value = _callLink.value.copy(name = callName)
}
fun setCallLink(callLink: String) {
_callLink.value = callLink
} }
} }
@@ -0,0 +1,10 @@
package org.thoughtcrime.securesms.calls.links.details
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.NavHostFragment
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.FragmentWrapperActivity
class CallLinkDetailsActivity : FragmentWrapperActivity() {
override fun getFragment(): Fragment = NavHostFragment.create(R.navigation.call_link_details)
}
@@ -0,0 +1,179 @@
package org.thoughtcrime.securesms.calls.links.details
import android.os.Bundle
import android.view.View
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.fragment.app.setFragmentResultListener
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import org.signal.core.ui.Dividers
import org.signal.core.ui.Rows
import org.signal.core.ui.Scaffolds
import org.signal.core.ui.theme.SignalTheme
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.calls.links.EditCallLinkNameDialogFragment
import org.thoughtcrime.securesms.calls.links.SignalCallRow
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.database.CallLinkTable
/**
* Provides detailed info about a call link and allows the owner of that link
* to modify call properties.
*/
class CallLinkDetailsFragment : ComposeFragment(), CallLinkDetailsCallback {
private val viewModel: CallLinkViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
parentFragmentManager.setFragmentResultListener(EditCallLinkNameDialogFragment.RESULT_KEY, viewLifecycleOwner) { resultKey, bundle ->
if (bundle.containsKey(resultKey)) {
viewModel.setName(bundle.getString(resultKey)!!)
}
}
}
@Composable
override fun FragmentContent() {
val isLoading by viewModel.isLoading
val callLink by viewModel.callLink
CallLinkDetails(
isLoading,
callLink,
this
)
}
override fun onNavigationClicked() {
findNavController().popBackStack()
}
override fun onJoinClicked() {
// TODO("Not yet implemented")
}
override fun onEditNameClicked() {
val name = viewModel.callLink.value.name
findNavController().navigate(
CallLinkDetailsFragmentDirections.actionCallLinkDetailsFragmentToEditCallLinkNameDialogFragment(name)
)
}
override fun onShareClicked() {
// TODO("Not yet implemented")
}
override fun onDeleteClicked() {
// TODO("Not yet implemented")
}
override fun onApproveAllMembersChanged(checked: Boolean) {
// TODO("Not yet implemented")
}
}
private interface CallLinkDetailsCallback {
fun onNavigationClicked()
fun onJoinClicked()
fun onEditNameClicked()
fun onShareClicked()
fun onDeleteClicked()
fun onApproveAllMembersChanged(checked: Boolean)
}
@Preview
@Composable
private fun CallLinkDetailsPreview() {
val avatarColor = remember {
AvatarColor.random()
}
val callLink = remember {
CallLinkTable.CallLink(
name = "Call Name",
identifier = "call-id-1",
isApprovalRequired = false,
avatarColor = avatarColor
)
}
SignalTheme(false) {
CallLinkDetails(
false,
callLink,
object : CallLinkDetailsCallback {
override fun onNavigationClicked() = Unit
override fun onJoinClicked() = Unit
override fun onEditNameClicked() = Unit
override fun onShareClicked() = Unit
override fun onDeleteClicked() = Unit
override fun onApproveAllMembersChanged(checked: Boolean) = Unit
}
)
}
}
@Composable
private fun CallLinkDetails(
isLoading: Boolean,
callLink: CallLinkTable.CallLink,
callback: CallLinkDetailsCallback
) {
Scaffolds.Settings(
title = stringResource(id = R.string.CallLinkDetailsFragment__call_details),
onNavigationClick = callback::onNavigationClicked,
navigationIconPainter = painterResource(id = R.drawable.ic_arrow_left_24)
) { paddingValues ->
if (isLoading) {
return@Settings
}
Column(modifier = Modifier.padding(paddingValues)) {
SignalCallRow(
callLink = callLink,
onJoinClicked = callback::onJoinClicked,
modifier = Modifier.padding(top = 16.dp, bottom = 12.dp)
)
Rows.TextRow(
text = stringResource(id = R.string.CallLinkDetailsFragment__add_call_name),
modifier = Modifier.clickable(onClick = callback::onEditNameClicked)
)
Rows.ToggleRow(
checked = callLink.isApprovalRequired,
text = stringResource(id = R.string.CallLinkDetailsFragment__approve_all_members),
onCheckChanged = callback::onApproveAllMembersChanged
)
Dividers.Default()
Rows.TextRow(
text = stringResource(id = R.string.CallLinkDetailsFragment__share_link),
icon = ImageVector.vectorResource(id = R.drawable.symbol_link_24),
modifier = Modifier.clickable(onClick = callback::onShareClicked)
)
Rows.TextRow(
text = stringResource(id = R.string.CallLinkDetailsFragment__delete_call_link),
icon = ImageVector.vectorResource(id = R.drawable.symbol_trash_24),
foregroundTint = MaterialTheme.colorScheme.error,
modifier = Modifier.clickable(onClick = callback::onDeleteClicked)
)
}
}
}
@@ -0,0 +1,22 @@
package org.thoughtcrime.securesms.calls.links.details
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.database.CallLinkTable
class CallLinkViewModel : ViewModel() {
private val isLoadingState: MutableState<Boolean> = mutableStateOf(true)
val isLoading: State<Boolean> = isLoadingState
private val callLinkState: MutableState<CallLinkTable.CallLink> = mutableStateOf(
CallLinkTable.CallLink("", "", AvatarColor.A120, false)
)
val callLink: State<CallLinkTable.CallLink> = callLinkState
fun setName(name: String) {
callLinkState.value = callLinkState.value.copy(name = name)
}
}
@@ -29,4 +29,22 @@ class AvatarColorPair private constructor(
} }
} }
} }
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as AvatarColorPair
if (foregroundColor != other.foregroundColor) return false
if (backgroundColor != other.backgroundColor) return false
return true
}
override fun hashCode(): Int {
var result = foregroundColor
result = 31 * result + backgroundColor
return result
}
} }
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.database
import android.content.Context import android.content.Context
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
/** /**
* Table containing ad-hoc call link details * Table containing ad-hoc call link details
@@ -21,4 +22,11 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
) )
""" """
} }
data class CallLink(
val name: String,
val identifier: String,
val avatarColor: AvatarColor,
val isApprovalRequired: Boolean
)
} }
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/call_link_details"
app:startDestination="@id/callLinkDetailsFragment">
<fragment
android:id="@+id/callLinkDetailsFragment"
android:name="org.thoughtcrime.securesms.calls.links.details.CallLinkDetailsFragment"
android:label="call_link_details">
<action
android:id="@+id/action_callLinkDetailsFragment_to_editCallLinkNameDialogFragment"
app:destination="@id/editCallLinkNameDialogFragment" />
</fragment>
<dialog
android:id="@+id/editCallLinkNameDialogFragment"
android:name="org.thoughtcrime.securesms.calls.links.EditCallLinkNameDialogFragment"
android:label="edit_call_link_name_dialog">
<argument
android:name="name"
app:argType="string"
app:nullable="false" />
</dialog>
</navigation>
@@ -31,7 +31,7 @@
<fragment <fragment
android:id="@+id/storiesLandingFragment" android:id="@+id/storiesLandingFragment"
android:name="org.thoughtcrime.securesms.stories.landing.StoriesLandingFragment" android:name="org.thoughtcrime.securesms.stories.landing.StoriesLandingFragment"
android:label="stories_landing_fragment" > android:label="stories_landing_fragment">
<action <action
android:id="@+id/action_storiesLandingFragment_to_callLogFragment" android:id="@+id/action_storiesLandingFragment_to_callLogFragment"
app:destination="@id/callLogFragment" /> app:destination="@id/callLogFragment" />
@@ -40,7 +40,7 @@
<fragment <fragment
android:id="@+id/callLogFragment" android:id="@+id/callLogFragment"
android:name="org.thoughtcrime.securesms.calls.log.CallLogFragment" android:name="org.thoughtcrime.securesms.calls.log.CallLogFragment"
android:label="call_log_fragment" > android:label="call_log_fragment">
<action <action
android:id="@+id/action_callLogFragment_to_storiesLandingFragment" android:id="@+id/action_callLogFragment_to_storiesLandingFragment"
app:destination="@id/storiesLandingFragment" /> app:destination="@id/storiesLandingFragment" />
@@ -52,6 +52,21 @@
<dialog <dialog
android:id="@+id/createCallLinkBottomSheet" android:id="@+id/createCallLinkBottomSheet"
android:name="org.thoughtcrime.securesms.calls.links.create.CreateCallLinkBottomSheetDialogFragment" android:name="org.thoughtcrime.securesms.calls.links.create.CreateCallLinkBottomSheetDialogFragment"
android:label="create_call_link_bottom_sheet" /> android:label="create_call_link_bottom_sheet">
<action
android:id="@+id/action_createCallLinkBottomSheet_to_editCallLinkNameDialogFragment"
app:destination="@id/editCallLinkNameDialogFragment" />
</dialog>
<dialog
android:id="@+id/editCallLinkNameDialogFragment"
android:name="org.thoughtcrime.securesms.calls.links.EditCallLinkNameDialogFragment"
android:label="edit_call_link_name_fragment">
<argument
android:name="name"
app:argType="string"
app:nullable="false" />
</dialog>
</navigation> </navigation>
+12
View File
@@ -5960,5 +5960,17 @@
<!-- Title shown at top of bottom sheet dialog for displaying a message\'s edit history --> <!-- Title shown at top of bottom sheet dialog for displaying a message\'s edit history -->
<string name="EditMessageHistoryDialog_title">Edit history</string> <string name="EditMessageHistoryDialog_title">Edit history</string>
<!-- CallLinkDetailsFragment -->
<!-- Displayed in action bar at the top of the fragment -->
<string name="CallLinkDetailsFragment__call_details">Call details</string>
<!-- Displayed in a text row, allowing the user to click and add a call name -->
<string name="CallLinkDetailsFragment__add_call_name">Add call name</string>
<!-- Displayed in a toggle row, allowing the user to click to enable or disable member approval -->
<string name="CallLinkDetailsFragment__approve_all_members">Approve all members</string>
<!-- Displayed in a text row, allowing the user to share the call link -->
<string name="CallLinkDetailsFragment__share_link">Share link</string>
<!-- Displayed in a text row, allowing the user to delete the call link -->
<string name="CallLinkDetailsFragment__delete_call_link">Delete call link</string>
<!-- EOF --> <!-- EOF -->
</resources> </resources>
@@ -21,6 +21,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@@ -102,7 +103,8 @@ object Rows {
fun TextRow( fun TextRow(
text: String, text: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
icon: ImageVector? = null icon: ImageVector? = null,
foregroundTint: Color = MaterialTheme.colorScheme.onSurface
) { ) {
if (icon != null) { if (icon != null) {
Row( Row(
@@ -113,14 +115,15 @@ object Rows {
Icon( Icon(
imageVector = icon, imageVector = icon,
contentDescription = null, contentDescription = null,
tint = MaterialTheme.colorScheme.onSurface tint = foregroundTint
) )
Spacer(modifier = Modifier.width(24.dp)) Spacer(modifier = Modifier.width(24.dp))
Text( Text(
text = text, text = text,
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f),
color = foregroundTint
) )
} }
} else { } else {