Convert InternalStoryDialogLauncherFragment to Compose.

This commit is contained in:
Alex Hart
2025-11-06 13:28:29 -04:00
committed by Michelle Tang
parent 4040b3badd
commit 2fad52abdc

View File

@@ -1,85 +1,194 @@
package org.thoughtcrime.securesms.components.settings.app.internal
import android.widget.Toast
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import org.signal.core.ui.compose.DayNightPreviews
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.Rows
import org.signal.core.ui.compose.Scaffolds
import org.signal.core.ui.compose.theme.SignalTheme
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.stories.dialogs.StoryDialogs
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
import org.thoughtcrime.securesms.util.DynamicTheme
class InternalStoryDialogLauncherFragment : DSLSettingsFragment(titleId = R.string.preferences__internal_stories_dialog_launcher) {
override fun bindAdapter(adapter: MappingAdapter) {
adapter.submitList(getConfiguration().toMappingModelList())
}
/**
* Internal tool for testing various story-related dialogs.
*/
class InternalStoryDialogLauncherFragment : ComposeFragment() {
private fun getConfiguration(): DSLConfiguration {
return configure {
clickPref(
title = DSLSettingsText.from("Remove group story"),
onClick = {
StoryDialogs.removeGroupStory(requireContext(), "Family") {
Toast.makeText(requireContext(), "Remove group story", Toast.LENGTH_SHORT).show()
}
}
)
@Composable
override fun FragmentContent() {
val callback = remember { DefaultInternalStoryDialogLauncherCallback() }
clickPref(
title = DSLSettingsText.from("Retry send"),
onClick = {
StoryDialogs.resendStory(requireContext()) {
Toast.makeText(requireContext(), "Retry send", Toast.LENGTH_SHORT).show()
}
}
)
clickPref(
title = DSLSettingsText.from("Story or profile selector"),
onClick = {
StoryDialogs.displayStoryOrProfileImage(
context = requireContext(),
onViewStory = { Toast.makeText(requireContext(), R.string.StoryDialogs__view_story, Toast.LENGTH_SHORT).show() },
onViewAvatar = { Toast.makeText(requireContext(), R.string.StoryDialogs__view_profile_photo, Toast.LENGTH_SHORT).show() }
)
}
)
clickPref(
title = DSLSettingsText.from("Hide story"),
onClick = {
StoryDialogs.hideStory(requireContext(), "Spiderman") {
Toast.makeText(requireContext(), "Hide story", Toast.LENGTH_SHORT).show()
}
}
)
clickPref(
title = DSLSettingsText.from("Turn off stories"),
onClick = {
StoryDialogs.disableStories(requireContext(), false) {
Toast.makeText(requireContext(), "Turn off stories", Toast.LENGTH_SHORT).show()
}
}
)
clickPref(
title = DSLSettingsText.from("Turn off stories (with stories on disk)"),
onClick = {
StoryDialogs.disableStories(requireContext(), true) {
Toast.makeText(requireContext(), "Turn off stories (with stories on disk)", Toast.LENGTH_SHORT).show()
}
}
)
clickPref(
title = DSLSettingsText.from("Delete custom story"),
onClick = {
StoryDialogs.deleteDistributionList(requireContext(), "Family") {
Toast.makeText(requireContext(), "Delete custom story", Toast.LENGTH_SHORT).show()
}
}
SignalTheme(isDarkMode = DynamicTheme.isDarkTheme(LocalContext.current)) {
InternalStoryDialogLauncherScreen(
callback = callback
)
}
}
/**
* Default callback implementation that launches story dialogs and displays toast notifications.
*/
inner class DefaultInternalStoryDialogLauncherCallback : InternalStoryDialogLauncherScreenCallback {
override fun onNavigationClick() {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
override fun onRemoveGroupStoryClick() {
StoryDialogs.removeGroupStory(requireContext(), "Family") {
Toast.makeText(requireContext(), "Remove group story", Toast.LENGTH_SHORT).show()
}
}
override fun onRetrySendClick() {
StoryDialogs.resendStory(requireContext()) {
Toast.makeText(requireContext(), "Retry send", Toast.LENGTH_SHORT).show()
}
}
override fun onStoryOrProfileSelectorClick() {
StoryDialogs.displayStoryOrProfileImage(
context = requireContext(),
onViewStory = { Toast.makeText(requireContext(), R.string.StoryDialogs__view_story, Toast.LENGTH_SHORT).show() },
onViewAvatar = { Toast.makeText(requireContext(), R.string.StoryDialogs__view_profile_photo, Toast.LENGTH_SHORT).show() }
)
}
override fun onHideStoryClick() {
StoryDialogs.hideStory(requireContext(), "Spiderman") {
Toast.makeText(requireContext(), "Hide story", Toast.LENGTH_SHORT).show()
}
}
override fun onTurnOffStoriesClick() {
StoryDialogs.disableStories(requireContext(), false) {
Toast.makeText(requireContext(), "Turn off stories", Toast.LENGTH_SHORT).show()
}
}
override fun onTurnOffStoriesWithStoriesOnDiskClick() {
StoryDialogs.disableStories(requireContext(), true) {
Toast.makeText(requireContext(), "Turn off stories (with stories on disk)", Toast.LENGTH_SHORT).show()
}
}
override fun onDeleteCustomStoryClick() {
StoryDialogs.deleteDistributionList(requireContext(), "Family") {
Toast.makeText(requireContext(), "Delete custom story", Toast.LENGTH_SHORT).show()
}
}
}
}
/**
* Screen displaying a list of story dialogs available for testing.
*/
@Composable
fun InternalStoryDialogLauncherScreen(
callback: InternalStoryDialogLauncherScreenCallback
) {
Scaffolds.Settings(
title = stringResource(R.string.preferences__internal_stories_dialog_launcher),
onNavigationClick = callback::onNavigationClick,
navigationIcon = ImageVector.vectorResource(R.drawable.symbol_arrow_start_24)
) { paddingValues ->
LazyColumn(
modifier = Modifier.padding(paddingValues)
) {
item {
Rows.TextRow(
text = "Remove group story",
modifier = Modifier.clickable(onClick = callback::onRemoveGroupStoryClick)
)
}
item {
Rows.TextRow(
text = "Retry send",
modifier = Modifier.clickable(onClick = callback::onRetrySendClick)
)
}
item {
Rows.TextRow(
text = "Story or profile selector",
modifier = Modifier.clickable(onClick = callback::onStoryOrProfileSelectorClick)
)
}
item {
Rows.TextRow(
text = "Hide story",
modifier = Modifier.clickable(onClick = callback::onHideStoryClick)
)
}
item {
Rows.TextRow(
text = "Turn off stories",
modifier = Modifier.clickable(onClick = callback::onTurnOffStoriesClick)
)
}
item {
Rows.TextRow(
text = "Turn off stories (with stories on disk)",
modifier = Modifier.clickable(onClick = callback::onTurnOffStoriesWithStoriesOnDiskClick)
)
}
item {
Rows.TextRow(
text = "Delete custom story",
modifier = Modifier.clickable(onClick = callback::onDeleteCustomStoryClick)
)
}
}
}
}
/**
* Callback interface for [InternalStoryDialogLauncherScreen] interactions.
*/
interface InternalStoryDialogLauncherScreenCallback {
fun onNavigationClick()
fun onRemoveGroupStoryClick()
fun onRetrySendClick()
fun onStoryOrProfileSelectorClick()
fun onHideStoryClick()
fun onTurnOffStoriesClick()
fun onTurnOffStoriesWithStoriesOnDiskClick()
fun onDeleteCustomStoryClick()
object Empty : InternalStoryDialogLauncherScreenCallback {
override fun onNavigationClick() = Unit
override fun onRemoveGroupStoryClick() = Unit
override fun onRetrySendClick() = Unit
override fun onStoryOrProfileSelectorClick() = Unit
override fun onHideStoryClick() = Unit
override fun onTurnOffStoriesClick() = Unit
override fun onTurnOffStoriesWithStoriesOnDiskClick() = Unit
override fun onDeleteCustomStoryClick() = Unit
}
}
@DayNightPreviews
@Composable
private fun InternalStoryDialogLauncherScreenPreview() {
Previews.Preview {
InternalStoryDialogLauncherScreen(
callback = InternalStoryDialogLauncherScreenCallback.Empty
)
}
}