mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-02 08:23:00 +01:00
Show conversation settings in the detail pane on large screens.
This commit is contained in:
committed by
Cody Henthorne
parent
9941b2d123
commit
4d301a4f66
@@ -30,6 +30,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.ui.getWindowSizeClass
|
||||
import org.signal.core.ui.isSplitPane
|
||||
import org.signal.core.ui.permissions.Permissions
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.signal.core.util.Result
|
||||
@@ -117,6 +119,7 @@ import org.thoughtcrime.securesms.util.ExpirationUtil
|
||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.WindowUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog
|
||||
@@ -261,8 +264,25 @@ class ConversationSettingsFragment :
|
||||
}
|
||||
}
|
||||
|
||||
private fun goToConversationList() {
|
||||
if (mainNavRouter != null) {
|
||||
mainNavRouter?.goTo(MainNavigationDetailLocation.Empty)
|
||||
} else {
|
||||
startActivity(MainActivity.clearTopAndOpenDetail(requireContext(), MainNavigationDetailLocation.Empty))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper {
|
||||
return object : Material3OnScrollHelper(activity = requireActivity(), views = listOf(toolbar!!), lifecycleOwner = viewLifecycleOwner) {
|
||||
return object : Material3OnScrollHelper(
|
||||
activity = requireActivity(),
|
||||
views = listOf(toolbar!!),
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
setStatusBarColor = { color ->
|
||||
if (!resources.getWindowSizeClass().isSplitPane() || activity is ConversationSettingsActivity) {
|
||||
WindowUtil.setStatusBarColor(requireActivity().window, color)
|
||||
}
|
||||
}
|
||||
) {
|
||||
override val inactiveColorSet = ColorSet(
|
||||
toolbarColorRes = CoreUiR.color.signal_colorBackground_0,
|
||||
statusBarColorRes = CoreUiR.color.signal_colorBackground
|
||||
@@ -972,7 +992,7 @@ class ConversationSettingsFragment :
|
||||
icon = DSLSettingsIcon.from(R.drawable.symbol_archive_24),
|
||||
onClick = {
|
||||
viewModel.toggleArchive()
|
||||
onToolbarNavigationClicked()
|
||||
goToConversationList()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -986,11 +1006,7 @@ class ConversationSettingsFragment :
|
||||
lifecycleScope.launch {
|
||||
viewModel.deleteChat()
|
||||
progressDialog.dismissAllowingStateLoss()
|
||||
if (mainNavRouter != null) {
|
||||
mainNavRouter?.goTo(MainNavigationDetailLocation.Empty)
|
||||
} else {
|
||||
startActivity(MainActivity.clearTopAndOpenDetail(requireContext(), MainNavigationDetailLocation.Empty))
|
||||
}
|
||||
goToConversationList()
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -1059,7 +1075,7 @@ class ConversationSettingsFragment :
|
||||
.onReportSpam()
|
||||
.subscribeBy {
|
||||
Toast.makeText(requireContext(), R.string.ConversationFragment_reported_as_spam, Toast.LENGTH_SHORT).show()
|
||||
onToolbarNavigationClicked()
|
||||
goToConversationList()
|
||||
}
|
||||
.addTo(lifecycleDisposable)
|
||||
},
|
||||
@@ -1073,7 +1089,7 @@ class ConversationSettingsFragment :
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
Toast.makeText(requireContext(), R.string.ConversationFragment_reported_as_spam_and_blocked, Toast.LENGTH_SHORT).show()
|
||||
onToolbarNavigationClicked()
|
||||
goToConversationList()
|
||||
}
|
||||
|
||||
is Result.Failure -> {
|
||||
@@ -1108,7 +1124,7 @@ class ConversationSettingsFragment :
|
||||
.onReportSpam()
|
||||
.subscribeBy {
|
||||
Toast.makeText(requireContext(), R.string.ConversationFragment_reported_as_spam, Toast.LENGTH_SHORT).show()
|
||||
onToolbarNavigationClicked()
|
||||
goToConversationList()
|
||||
}
|
||||
.addTo(lifecycleDisposable)
|
||||
},
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.conversation
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsActivity
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
class ConversationSettingsNavHostFragment : NavHostFragment() {
|
||||
|
||||
companion object {
|
||||
suspend fun createArgs(recipientId: RecipientId): Bundle {
|
||||
val recipient = withContext(Dispatchers.IO) { Recipient.resolved(recipientId) }
|
||||
|
||||
val args = if (recipient.isGroup) {
|
||||
ConversationSettingsFragmentArgs.Builder(null, recipient.requireGroupId(), null)
|
||||
} else {
|
||||
ConversationSettingsFragmentArgs.Builder(recipientId, null, null)
|
||||
}.build()
|
||||
|
||||
return bundleOf(DSLSettingsActivity.ARG_START_BUNDLE to args.toBundle())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val args = requireArguments().getBundle(DSLSettingsActivity.ARG_START_BUNDLE)
|
||||
navController.setGraph(R.navigation.conversation_settings, args)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
}
|
||||
@@ -4129,7 +4129,7 @@ class ConversationFragment :
|
||||
|
||||
override fun handleManageGroup() {
|
||||
viewModel.recipientSnapshot?.let { recipient ->
|
||||
navigateToConversationSettingsStandalone(recipient)
|
||||
navigateTo(MainNavigationDetailLocation.Chats.ConversationSettings(recipient.id))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4166,7 +4166,7 @@ class ConversationFragment :
|
||||
override fun handleConversationSettings() {
|
||||
viewModel.recipientSnapshot?.let { recipient ->
|
||||
if (!viewModel.hasMessageRequestState || recipient.isBlocked) {
|
||||
navigateToConversationSettingsStandalone(recipient)
|
||||
navigateTo(MainNavigationDetailLocation.Chats.ConversationSettings(recipient.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4235,6 +4235,7 @@ class ConversationFragment :
|
||||
} else {
|
||||
when (location) {
|
||||
is MainNavigationDetailLocation.Chats.MessageDetails -> navigateToMessageDetailsStandalone(location)
|
||||
is MainNavigationDetailLocation.Chats.ConversationSettings -> navigateToConversationSettingsStandalone(viewModel.recipientSnapshot!!)
|
||||
is MainNavigationDetailLocation.Chats.Conversation -> error("ConversationFragment shouldn't navigate to another conversation - use the main navigation infrastructure instead.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.thoughtcrime.securesms.main
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.compose.animation.core.Transition
|
||||
import androidx.compose.animation.core.animateDp
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
@@ -22,6 +23,7 @@ import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -47,6 +49,7 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.ui.isSplitPane
|
||||
import org.thoughtcrime.securesms.MainNavigator
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.ConversationSettingsNavHostFragment
|
||||
import org.thoughtcrime.securesms.compose.FragmentBackHandler
|
||||
import org.thoughtcrime.securesms.compose.FragmentBackPressedState
|
||||
import org.thoughtcrime.securesms.conversation.ConversationArgs
|
||||
@@ -162,12 +165,44 @@ fun NavGraphBuilder.chatNavGraphBuilder(
|
||||
clazz = MessageDetailsFragment::class.java,
|
||||
fragmentState = fragmentState,
|
||||
arguments = MessageDetailsFragment.args(route.recipientId, route.messageId),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.statusBarsPadding()
|
||||
.navigationBarsPadding()
|
||||
)
|
||||
}
|
||||
|
||||
composable<MainNavigationDetailLocation.Chats.ConversationSettings>(
|
||||
typeMap = mapOf(
|
||||
typeOf<RecipientId>() to JsonSerializableNavType(RecipientId.serializer())
|
||||
)
|
||||
) { navBackStackEntry ->
|
||||
|
||||
val navigatorProvider = LocalContext.current as? MainNavigator.NavigatorProvider
|
||||
val fragmentState = key(route) { rememberFragmentState() }
|
||||
val route = navBackStackEntry.toRoute<MainNavigationDetailLocation.Chats.ConversationSettings>()
|
||||
val arguments: Bundle? by produceState(null, route.recipientId) {
|
||||
value = ConversationSettingsNavHostFragment.createArgs(route.recipientId)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
navigatorProvider?.onFirstRender()
|
||||
}
|
||||
|
||||
arguments?.let { args ->
|
||||
AndroidFragment(
|
||||
clazz = ConversationSettingsNavHostFragment::class.java,
|
||||
fragmentState = fragmentState,
|
||||
arguments = args,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.statusBarsPadding()
|
||||
.navigationBarsPadding()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -73,6 +73,13 @@ sealed class MainNavigationDetailLocation : Parcelable {
|
||||
@IgnoredOnParcel
|
||||
override val controllerKey: RecipientId = recipientId
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ConversationSettings(val recipientId: RecipientId) : Chats() {
|
||||
@Transient
|
||||
@IgnoredOnParcel
|
||||
override val controllerKey: RecipientId = recipientId
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user