Add internal preferences under Advanced behind feature flag.

Initially for GV2 testing.
master
Alan Evans 2020-07-06 18:52:29 -03:00 committed by Greyson Parrelli
parent 545ba80697
commit e6a0e5b858
11 changed files with 150 additions and 12 deletions

View File

@ -271,7 +271,7 @@ public final class ContactSelectionListFragment extends LoggingFragment
RecyclerViewConcatenateAdapterStickyHeader concatenateAdapter = new RecyclerViewConcatenateAdapterStickyHeader();
if (listCallback != null) {
if (FeatureFlags.groupsV2create() && FeatureFlags.groupsV2internalTest()) {
if (FeatureFlags.groupsV2create() && FeatureFlags.internalUser()) {
headerAdapter = new FixedViewsAdapter(createNewGroupItem(listCallback), createNewGroupsV1GroupItem(listCallback));
} else {
headerAdapter = new FixedViewsAdapter(createNewGroupItem(listCallback));

View File

@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.v2.GroupCandidateHelper;
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
@ -117,6 +118,10 @@ final class GroupManagerV2 {
GroupCandidate self = groupCandidateHelper.recipientIdToCandidate(Recipient.self().getId());
Set<GroupCandidate> candidates = new HashSet<>(groupCandidateHelper.recipientIdsToCandidates(members));
if (SignalStore.internalValues().forceGv2Invites()) {
candidates = GroupCandidate.withoutProfileKeyCredentials(candidates);
}
if (!self.hasProfileKeyCredential()) {
Log.w(TAG, "Cannot create a V2 group as self does not have a versioned profile");
throw new MembershipNotSuitableForV2Exception("Cannot create a V2 group as self does not have a versioned profile");
@ -186,6 +191,11 @@ final class GroupManagerV2 {
}
Set<GroupCandidate> groupCandidates = groupCandidateHelper.recipientIdsToCandidates(new HashSet<>(newMembers));
if (SignalStore.internalValues().forceGv2Invites()) {
groupCandidates = GroupCandidate.withoutProfileKeyCredentials(groupCandidates);
}
return commitChangeWithConflictResolution(groupOperations.createModifyGroupMembershipChange(groupCandidates, selfUuid));
}

View File

@ -0,0 +1,20 @@
package org.thoughtcrime.securesms.keyvalue;
import org.thoughtcrime.securesms.util.FeatureFlags;
public final class InternalValues extends SignalStoreValues {
public static final String GV2_FORCE_INVITES = "internal.gv2.force_invites";
InternalValues(KeyValueStore store) {
super(store);
}
@Override
void onFirstEverAppLaunch() {
}
public synchronized boolean forceGv2Invites() {
return FeatureFlags.internalUser() && getBoolean(GV2_FORCE_INVITES, false);
}
}

View File

@ -23,6 +23,7 @@ public final class SignalStore {
private final UiHints uiHints;
private final TooltipValues tooltipValues;
private final MiscellaneousValues misc;
private final InternalValues internalValues;
private SignalStore() {
this.store = ApplicationDependencies.getKeyValueStore();
@ -34,6 +35,7 @@ public final class SignalStore {
this.uiHints = new UiHints(store);
this.tooltipValues = new TooltipValues(store);
this.misc = new MiscellaneousValues(store);
this.internalValues = new InternalValues(store);
}
public static void onFirstEverAppLaunch() {
@ -45,6 +47,7 @@ public final class SignalStore {
uiHints().onFirstEverAppLaunch();
tooltips().onFirstEverAppLaunch();
misc().onFirstEverAppLaunch();
internalValues().onFirstEverAppLaunch();
}
public static @NonNull KbsValues kbsValues() {
@ -79,6 +82,10 @@ public final class SignalStore {
return INSTANCE.misc;
}
public static @NonNull InternalValues internalValues() {
return INSTANCE.internalValues;
}
public static @NonNull GroupsV2AuthorizationSignalStoreCache groupsV2AuthorizationCache() {
return new GroupsV2AuthorizationSignalStoreCache(getStore());
}

View File

@ -16,19 +16,19 @@ import androidx.appcompat.app.AlertDialog;
import androidx.preference.CheckBoxPreference;
import androidx.preference.Preference;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.contacts.ContactIdentityManager;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity;
import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.whispersystems.libsignal.util.guava.Optional;
@ -42,6 +42,7 @@ public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment {
private static final String PUSH_MESSAGING_PREF = "pref_toggle_push_messaging";
private static final String SUBMIT_DEBUG_LOG_PREF = "pref_submit_debug_logs";
private static final String INTERNAL_PREF = "pref_internal";
private static final int PICK_IDENTITY_CONTACT = 1;
@ -54,6 +55,22 @@ public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment {
Preference submitDebugLog = this.findPreference(SUBMIT_DEBUG_LOG_PREF);
submitDebugLog.setOnPreferenceClickListener(new SubmitDebugLogListener());
submitDebugLog.setSummary(getVersion(getActivity()));
Preference internalPreference = this.findPreference(INTERNAL_PREF);
internalPreference.setVisible(FeatureFlags.internalUser());
internalPreference.setOnPreferenceClickListener(preference -> {
if (FeatureFlags.internalUser()) {
requireActivity().getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.slide_from_end, R.anim.slide_to_start, R.anim.slide_from_start, R.anim.slide_to_end)
.replace(android.R.id.content, new InternalOptionsPreferenceFragment())
.addToBackStack(null)
.commit();
return true;
} else {
return false;
}
});
}
@Override

View File

@ -0,0 +1,39 @@
package org.thoughtcrime.securesms.preferences;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceDataStore;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
import org.thoughtcrime.securesms.keyvalue.InternalValues;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
public class InternalOptionsPreferenceFragment extends CorrectedPreferenceFragment {
private static final String TAG = Log.tag(InternalOptionsPreferenceFragment.class);
@Override
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_internal);
PreferenceDataStore preferenceDataStore = SignalStore.getPreferenceDataStore();
SwitchPreferenceCompat forceGv2Preference = (SwitchPreferenceCompat) this.findPreference(InternalValues.GV2_FORCE_INVITES);
forceGv2Preference.setPreferenceDataStore(preferenceDataStore);
forceGv2Preference.setChecked(SignalStore.internalValues().forceGv2Invites());
}
@Override
public void onResume() {
super.onResume();
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__internal_preferences);
}
}

View File

@ -62,8 +62,8 @@ public final class FeatureFlags {
private static final String GROUPS_V2 = "android.groupsv2";
private static final String GROUPS_V2_CREATE = "android.groupsv2.create";
private static final String GROUPS_V2_CAPACITY = "android.groupsv2.capacity";
private static final String GROUPS_V2_INTERNAL_TEST = "android.groupsv2.internalTest";
private static final String CDS = "android.cds";
private static final String INTERNAL_USER = "android.internalUser";
/**
* We will only store remote values for flags in this set. If you want a flag to be controllable
@ -82,7 +82,7 @@ public final class FeatureFlags {
GROUPS_V2,
GROUPS_V2_CREATE,
GROUPS_V2_CAPACITY,
GROUPS_V2_INTERNAL_TEST
INTERNAL_USER
);
/**
@ -252,9 +252,9 @@ public final class FeatureFlags {
return getInteger(GROUPS_V2_CAPACITY, 100);
}
/** Groups v2 UI for internal testing. */
public static boolean groupsV2internalTest() {
return groupsV2() && getBoolean(GROUPS_V2_INTERNAL_TEST, false);
/** Internal testing extensions. */
public static boolean internalUser() {
return getBoolean(INTERNAL_USER, false);
}
/** Whether or not to use the new contact discovery service endpoint, which supports UUIDs. */

View File

@ -1941,6 +1941,12 @@
<string name="preferences_communication__sealed_sender_allow_from_anyone_description">Enable sealed sender for incoming messages from non-contacts and people with whom you have not shared your profile.</string>
<string name="preferences_communication__sealed_sender_learn_more">Learn more</string>
<!-- Internal only preferences -->
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
<string name="preferences__internal_preferences_groups_v2" translatable="false">Groups V2</string>
<string name="preferences__internal_force_gv2_invites" translatable="false">Force Invites</string>
<string name="preferences__internal_force_gv2_invites_description" translatable="false">Members will not be added directly to a GV2 even if they could be.</string>
<!-- **************************************** -->
<!-- menus -->
<!-- **************************************** -->

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_toggle_push_messaging"
@ -13,4 +14,9 @@
<Preference android:key="pref_submit_debug_logs"
android:title="@string/preferences__submit_debug_log"/>
<Preference android:key="pref_internal"
android:title="@string/preferences__internal_preferences"
app:isPreferenceVisible="false" />
</PreferenceScreen>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="internal_groupsV2"
android:title="@string/preferences__internal_preferences_groups_v2">
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:defaultValue="false"
android:key="internal.gv2.force_invites"
android:summary="@string/preferences__internal_force_gv2_invites_description"
android:title="@string/preferences__internal_force_gv2_invites" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -5,7 +5,9 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
/**
@ -39,6 +41,21 @@ public final class GroupCandidate {
return profileKeyCredential.isPresent();
}
public static Set<GroupCandidate> withoutProfileKeyCredentials(Set<GroupCandidate> groupCandidates) {
HashSet<GroupCandidate> result = new HashSet<>(groupCandidates.size());
for (GroupCandidate candidate: groupCandidates) {
result.add(candidate.withoutProfileKeyCredential());
}
return result;
}
public GroupCandidate withoutProfileKeyCredential() {
return hasProfileKeyCredential() ? new GroupCandidate(uuid, Optional.absent())
: this;
}
public GroupCandidate withProfileKeyCredential(ProfileKeyCredential profileKeyCredential) {
return new GroupCandidate(uuid, Optional.of(profileKeyCredential));
}