Make same-group-membership helper available for all users.

This commit is contained in:
Greyson Parrelli 2026-06-23 15:54:35 -04:00 committed by jeffrey-signal
parent 9dac02fa1c
commit 72050dbe64
No known key found for this signature in database
8 changed files with 54 additions and 41 deletions

View File

@ -9,7 +9,6 @@ sealed interface LabsSettingsEvents {
data class ToggleIndividualChatPlaintextExport(val enabled: Boolean) : LabsSettingsEvents
data class ToggleStoryArchive(val enabled: Boolean) : LabsSettingsEvents
data class ToggleIncognito(val enabled: Boolean) : LabsSettingsEvents
data class ToggleGroupSuggestionsForMembers(val enabled: Boolean) : LabsSettingsEvents
data class ToggleBetterSearch(val enabled: Boolean) : LabsSettingsEvents
data class ToggleAutoLowerHand(val enabled: Boolean) : LabsSettingsEvents
data class ToggleStarredMessages(val enabled: Boolean) : LabsSettingsEvents

View File

@ -116,15 +116,6 @@ private fun LabsSettingsContent(
)
}
item {
Rows.ToggleRow(
checked = state.groupSuggestionsForMembers,
text = "Group Suggestions for Members",
label = "When creating a group, show existing groups that have the exact same members.",
onCheckChanged = { onEvent(LabsSettingsEvents.ToggleGroupSuggestionsForMembers(it)) }
)
}
item {
Rows.ToggleRow(
checked = state.betterSearch,

View File

@ -12,7 +12,6 @@ data class LabsSettingsState(
val individualChatPlaintextExport: Boolean = false,
val storyArchive: Boolean = false,
val incognito: Boolean = false,
val groupSuggestionsForMembers: Boolean = false,
val betterSearch: Boolean = false,
val autoLowerHand: Boolean = false,
val starredMessages: Boolean = false

View File

@ -29,10 +29,6 @@ class LabsSettingsViewModel : ViewModel() {
SignalStore.labs.incognito = event.enabled
_state.value = _state.value.copy(incognito = event.enabled)
}
is LabsSettingsEvents.ToggleGroupSuggestionsForMembers -> {
SignalStore.labs.groupSuggestionsForMembers = event.enabled
_state.value = _state.value.copy(groupSuggestionsForMembers = event.enabled)
}
is LabsSettingsEvents.ToggleBetterSearch -> {
SignalStore.labs.betterSearch = event.enabled
_state.value = _state.value.copy(betterSearch = event.enabled)
@ -54,7 +50,6 @@ class LabsSettingsViewModel : ViewModel() {
individualChatPlaintextExport = SignalStore.labs.individualChatPlaintextExport,
storyArchive = SignalStore.labs.storyArchive,
incognito = SignalStore.labs.incognito,
groupSuggestionsForMembers = SignalStore.labs.groupSuggestionsForMembers,
betterSearch = SignalStore.labs.betterSearch,
autoLowerHand = SignalStore.labs.autoLowerHand,
starredMessages = SignalStore.labs.starredMessages

View File

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.groups.ui.creategroup.details;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
@ -155,27 +156,35 @@ public class AddGroupDetailsFragment extends LoggingFragment {
});
View sameGroupsSection = view.findViewById(R.id.same_groups_section);
TextView sameGroupsHeader = view.findViewById(R.id.same_groups_header);
ChipGroup sameGroupsChipGroup = view.findViewById(R.id.same_groups_chip_group);
if (SignalStore.labs().getGroupSuggestionsForMembers()) {
viewModel.getSameGroups().observe(getViewLifecycleOwner(), groups -> {
sameGroupsChipGroup.removeAllViews();
if (groups.isEmpty()) {
sameGroupsSection.setVisibility(View.GONE);
} else {
sameGroupsSection.setVisibility(View.VISIBLE);
RequestManager requestManager = Glide.with(this);
for (Recipient group : groups) {
ContactChip chip = new ContactChip(requireContext());
chip.setText(group.getDisplayName(requireContext()));
chip.setAvatar(requestManager, group, null);
chip.setCloseIconVisible(false);
chip.setOnClickListener(v -> navigateToConversation(group.getId()));
sameGroupsChipGroup.addView(chip);
}
viewModel.getSameGroups().observe(getViewLifecycleOwner(), groups -> {
sameGroupsChipGroup.removeAllViews();
if (groups.isEmpty()) {
sameGroupsSection.setVisibility(View.GONE);
} else {
sameGroupsSection.setVisibility(View.VISIBLE);
sameGroupsHeader.setText(getResources().getQuantityString(R.plurals.AddGroupDetailsFragment__d_groups_with_same_members, groups.size(), groups.size()));
RequestManager requestManager = Glide.with(this);
ColorStateList chevronTint = ColorStateList.valueOf(ContextCompat.getColor(requireContext(), org.signal.core.ui.R.color.signal_colorOnSurface));
for (Recipient group : groups) {
ContactChip chip = new ContactChip(requireContext());
chip.setText(group.getDisplayName(requireContext()));
chip.setAvatar(requestManager, group, null);
chip.setCloseIcon(ContextCompat.getDrawable(requireContext(), R.drawable.symbol_chevron_right_compact_bold_16));
chip.setCloseIconSize(ViewUtil.dpToPx(14));
chip.setCloseIconEndPadding(0);
chip.setCloseIconStartPadding(0);
chip.setCloseIconTint(chevronTint);
chip.setCloseIconVisible(true);
chip.setOnClickListener(v -> confirmNavigateToConversation(group));
chip.setOnCloseIconClickListener(v -> confirmNavigateToConversation(group));
sameGroupsChipGroup.addView(chip);
}
});
}
}
});
name.requestFocus();
@ -293,6 +302,19 @@ public class AddGroupDetailsFragment extends LoggingFragment {
create.setEnabled(isEnabled);
}
private void confirmNavigateToConversation(@NonNull Recipient group) {
new MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.AddGroupDetailsFragment__discard_group)
.setMessage(getString(R.string.AddGroupDetailsFragment__if_you_continue_to_the_group_s_your_changes_wont_be_saved, group.getDisplayName(requireContext())))
.setCancelable(true)
.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel())
.setPositiveButton(R.string.AddGroupDetailsFragment__discard, (dialog, which) -> {
dialog.dismiss();
navigateToConversation(group.getId());
})
.show();
}
private void navigateToConversation(@NonNull RecipientId groupRecipientId) {
ConversationIntents.createBuilder(requireContext(), groupRecipientId, -1L)
.subscribe(builder -> {

View File

@ -7,7 +7,6 @@ class LabsValues internal constructor(store: KeyValueStore) : SignalStoreValues(
const val INDIVIDUAL_CHAT_PLAINTEXT_EXPORT: String = "labs.individual_chat_plaintext_export"
const val STORY_ARCHIVE: String = "labs.story_archive"
const val INCOGNITO: String = "labs.incognito"
const val GROUP_SUGGESTIONS_FOR_MEMBERS: String = "labs.group_suggestions_for_members"
const val BETTER_SEARCH: String = "labs.better_search"
const val AUTO_LOWER_HAND: String = "labs.auto_lower_hand"
const val STARRED_MESSAGES: String = "labs.starred_messages"
@ -23,8 +22,6 @@ class LabsValues internal constructor(store: KeyValueStore) : SignalStoreValues(
var incognito by booleanValue(INCOGNITO, true).falseForExternalUsers()
var groupSuggestionsForMembers by booleanValue(GROUP_SUGGESTIONS_FOR_MEMBERS, true).falseForExternalUsers()
var betterSearch by booleanValue(BETTER_SEARCH, true).falseForExternalUsers()
var autoLowerHand by booleanValue(AUTO_LOWER_HAND, true).falseForExternalUsers()

View File

@ -128,13 +128,14 @@
tools:visibility="visible">
<TextView
android:id="@+id/same_groups_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="40dp"
android:paddingHorizontal="@dimen/dsl_settings_gutter"
android:text="@string/AddGroupDetailsFragment__groups_with_same_members"
android:textAppearance="@style/Signal.Text.TitleSmall" />
android:textAppearance="@style/Signal.Text.TitleSmall"
tools:text="4 groups with the same members" />
<HorizontalScrollView
android:layout_width="match_parent"

View File

@ -1452,6 +1452,12 @@
<string name="AddGroupDetailsFragment__remove">Remove</string>
<string name="AddGroupDetailsFragment__sms_contact">SMS contact</string>
<string name="AddGroupDetailsFragment__remove_s_from_this_group">Remove %1$s from this group?</string>
<!-- Title of the dialog shown when tapping an existing group while creating a new group, confirming the user wants to leave and discard their in-progress group -->
<string name="AddGroupDetailsFragment__discard_group">Discard group?</string>
<!-- Body of the dialog shown when tapping an existing group while creating a new group. Placeholder is the name of the group being navigated to. -->
<string name="AddGroupDetailsFragment__if_you_continue_to_the_group_s_your_changes_wont_be_saved">If you continue to the group \"%1$s\" your changes won\'t be saved.</string>
<!-- Label for the button that confirms discarding the in-progress group and navigating to an existing group -->
<string name="AddGroupDetailsFragment__discard">Discard</string>
<!-- Info message shown in the middle of the screen, displayed when adding group details to an MMS Group -->
<string name="AddGroupDetailsFragment__youve_selected_a_contact_that_doesnt_support">You\'ve selected a contact that doesn\'t support Signal groups, so this group will be MMS. Custom MMS group names and photos will only be visible to you.</string>
<!-- Info message shown in the middle of the screen, displayed when adding group details to an MMS Group after SMS Phase 0 -->
@ -9840,8 +9846,11 @@
<!-- Body for screen shown to let the user know that displaying their member label will take priority over their about text. -->
<string name="MemberLabelsAboutOverride__body">In this group, your Member Label will be displayed beside your photo in place of your About.</string>
<!-- Label for internal-only section showing groups with same members -->
<string name="AddGroupDetailsFragment__groups_with_same_members" translatable="false">Groups with same members (Labs)</string>
<!-- Header for the section shown when creating a group that lists existing groups with the exact same members. Includes the number of such groups. -->
<plurals name="AddGroupDetailsFragment__d_groups_with_same_members">
<item quantity="one">%1$d group with the same members</item>
<item quantity="other">%1$d groups with the same members</item>
</plurals>
<!-- Title of the sheet shown when a local backup restore could not be completed -->
<string name="CouldNotCompleteBackupRestoreSheet__title">Can\'t restore backup</string>