Skip to content

Commit

Permalink
New group avatar and name selection screen.
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-signal authored and greyson-signal committed May 13, 2020
1 parent 12b7d6c commit 5eb663a
Show file tree
Hide file tree
Showing 22 changed files with 491 additions and 187 deletions.
Expand Up @@ -7,19 +7,34 @@

public class ClearProfileAvatarActivity extends Activity {

private static final String ARG_TITLE = "arg_title";

public static Intent createForUserProfilePhoto() {
return new Intent("org.thoughtcrime.securesms.action.CLEAR_PROFILE_PHOTO");
}

public static Intent createForGroupProfilePhoto() {
Intent intent = new Intent("org.thoughtcrime.securesms.action.CLEAR_PROFILE_PHOTO");
intent.putExtra(ARG_TITLE, R.string.ClearProfileActivity_remove_group_photo);
return intent;
}

@Override
public void onResume() {
super.onResume();

int titleId = getIntent().getIntExtra(ARG_TITLE, R.string.ClearProfileActivity_remove_profile_photo);

new AlertDialog.Builder(this)
.setTitle(R.string.ClearProfileActivity_remove_profile_photo)
.setTitle(titleId)
.setNegativeButton(android.R.string.cancel, (dialog, which) -> finish())
.setPositiveButton(R.string.ClearProfileActivity_remove, (dialog, which) -> {
Intent result = new Intent();
result.putExtra("delete", true);
setResult(Activity.RESULT_OK, result);
finish();
})
.setOnCancelListener(dialog -> finish())
.show();
}

Expand Down
Expand Up @@ -65,11 +65,13 @@
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.profiles.edit.EditProfileActivity;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter;
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter.OnRecipientDeletedListener;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
Expand Down Expand Up @@ -203,7 +205,7 @@ private void initializeResources() {
recipientsPanel.setPanelChangeListener(this);
findViewById(R.id.contacts_button).setOnClickListener(new AddRecipientButtonListener());
avatar.setImageDrawable(getDefaultGroupAvatar());
avatar.setOnClickListener(view -> AvatarSelectionBottomSheetDialogFragment.create(avatarBmp != null, false, REQUEST_CODE_SELECT_AVATAR).show(getSupportFragmentManager(), null));
avatar.setOnClickListener(view -> AvatarSelectionBottomSheetDialogFragment.create(avatarBmp != null, false, REQUEST_CODE_SELECT_AVATAR, true).show(getSupportFragmentManager(), null));
}

private Drawable getDefaultGroupAvatar() {
Expand All @@ -215,6 +217,10 @@ private void initializeExistingGroup() {

if (groupId != null) {
new FillExistingGroupInfoAsyncTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, groupId);

if (FeatureFlags.newGroupUI() && groupId.isPush()) {
avatar.setOnClickListener(v -> startActivity(EditProfileActivity.getIntentForGroupProfile(this, groupId.requirePush())));
}
}
}

Expand Down
Expand Up @@ -193,6 +193,7 @@
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.profiles.GroupShareProfileView;
import org.thoughtcrime.securesms.profiles.edit.EditProfileActivity;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;
Expand Down
Expand Up @@ -9,15 +9,19 @@

import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.groups.UuidCiphertext;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
import org.whispersystems.signalservice.api.util.InvalidNumberException;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public final class GroupManager {
Expand All @@ -33,6 +37,20 @@ public final class GroupManager {
return V1GroupManager.createGroup(context, addresses, avatar, name, mms);
}

@WorkerThread
public static GroupActionResult updateGroup(@NonNull Context context,
@NonNull GroupId groupId,
@Nullable byte[] avatar,
@Nullable String name)
throws InvalidNumberException
{

List<Recipient> members = DatabaseFactory.getGroupDatabase(context)
.getGroupMembers(groupId, GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);

return V1GroupManager.updateGroup(context, groupId, getMemberIds(members), avatar, name);
}

public static GroupActionResult updateGroup(@NonNull Context context,
@NonNull GroupId groupId,
@NonNull Set<Recipient> members,
Expand All @@ -42,7 +60,7 @@ public static GroupActionResult updateGroup(@NonNull Context context,
{
Set<RecipientId> addresses = getMemberIds(members);

return V1GroupManager.updateGroup(context, groupId, addresses, avatar, name);
return V1GroupManager.updateGroup(context, groupId, addresses, BitmapUtil.toByteArray(avatar), name);
}

private static Set<RecipientId> getMemberIds(Collection<Recipient> recipients) {
Expand Down
Expand Up @@ -87,13 +87,12 @@ final class V1GroupManager {
static GroupActionResult updateGroup(@NonNull Context context,
@NonNull GroupId groupId,
@NonNull Set<RecipientId> memberAddresses,
@Nullable Bitmap avatar,
@Nullable byte[] avatarBytes,
@Nullable String name)
throws InvalidNumberException
{
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
final RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(groupId);
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);

memberAddresses.add(Recipient.self().getId());
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
Expand Down
Expand Up @@ -5,6 +5,9 @@
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
Expand All @@ -29,6 +32,7 @@
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.profiles.edit.EditProfileActivity;
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;

import java.util.Objects;
Expand Down Expand Up @@ -68,6 +72,12 @@ static ManageGroupFragment newInstance(@NonNull String groupId) {
return fragment;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}

@Override
public @Nullable View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
Expand Down Expand Up @@ -99,7 +109,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

Context context = requireContext();
GroupId.Push groupId = GroupId.parseOrThrow(Objects.requireNonNull(requireArguments().getString(GROUP_ID))).requirePush();
GroupId.Push groupId = getPushGroupId();
ManageGroupViewModel.Factory factory = new ManageGroupViewModel.Factory(context, groupId);

viewModel = ViewModelProviders.of(requireActivity(), factory).get(ManageGroupViewModel.class);
Expand Down Expand Up @@ -177,6 +187,27 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
groupMemberList.setRecipientClickListener(recipient -> RecipientBottomSheetDialogFragment.create(recipient.getId(), groupId).show(requireFragmentManager(), "BOTTOM"));
}

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.manage_group_fragment, menu);

viewModel.getCanEditGroupAttributes().observe(getViewLifecycleOwner(), canEdit -> menu.findItem(R.id.action_edit).setVisible(canEdit));
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.action_edit) {
startActivity(EditProfileActivity.getIntentForGroupProfile(requireActivity(), getPushGroupId()));
return true;
}

return false;
}

private GroupId.Push getPushGroupId() {
return GroupId.parseOrThrow(Objects.requireNonNull(requireArguments().getString(GROUP_ID))).requirePush();
}

private void setMediaCursorFactory(@Nullable ManageGroupViewModel.CursorFactory cursorFactory) {
if (this.cursorFactory != cursorFactory) {
this.cursorFactory = cursorFactory;
Expand Down
Expand Up @@ -19,7 +19,9 @@
import com.annimon.stream.Stream;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

import org.thoughtcrime.securesms.ClearProfileAvatarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.util.ThemeUtil;

import java.util.ArrayList;
Expand All @@ -29,8 +31,9 @@ public class AvatarSelectionBottomSheetDialogFragment extends BottomSheetDialogF

private static final String ARG_OPTIONS = "options";
private static final String ARG_REQUEST_CODE = "request_code";
private static final String ARG_IS_GROUP = "is_group";

public static DialogFragment create(boolean includeClear, boolean includeCamera, short resultCode) {
public static DialogFragment create(boolean includeClear, boolean includeCamera, short resultCode, boolean isGroup) {
DialogFragment fragment = new AvatarSelectionBottomSheetDialogFragment();
List<SelectionOption> selectionOptions = new ArrayList<>(3);
Bundle args = new Bundle();
Expand All @@ -51,6 +54,7 @@ public static DialogFragment create(boolean includeClear, boolean includeCamera,

args.putStringArray(ARG_OPTIONS, options);
args.putShort(ARG_REQUEST_CODE, resultCode);
args.putBoolean(ARG_IS_GROUP, isGroup);
fragment.setArguments(args);

return fragment;
Expand Down Expand Up @@ -93,7 +97,7 @@ private List<SelectionOption> getOptionsFromArguments() {
}

private void launchOptionAndDismiss(@NonNull SelectionOption option) {
Intent intent = createIntent(requireContext(), option);
Intent intent = createIntent(requireContext(), option, requireArguments().getBoolean(ARG_IS_GROUP));

int requestCode = requireArguments().getShort(ARG_REQUEST_CODE);
if (getParentFragment() != null) {
Expand All @@ -105,14 +109,15 @@ private void launchOptionAndDismiss(@NonNull SelectionOption option) {
dismiss();
}

private static Intent createIntent(@NonNull Context context, @NonNull SelectionOption selectionOption) {
private static Intent createIntent(@NonNull Context context, @NonNull SelectionOption selectionOption, boolean isGroup) {
switch (selectionOption) {
case CAPTURE:
return AvatarSelectionActivity.getIntentForCameraCapture(context);
case GALLERY:
return AvatarSelectionActivity.getIntentForGallery(context);
case DELETE:
return new Intent("org.thoughtcrime.securesms.action.CLEAR_PROFILE_PHOTO");
return isGroup ? ClearProfileAvatarActivity.createForGroupProfilePhoto()
: ClearProfileAvatarActivity.createForUserProfilePhoto();
default:
throw new IllegalStateException("Unknown option: " + selectionOption);
}
Expand Down
Expand Up @@ -28,7 +28,6 @@
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.MainActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.lock.v2.KbsConstants;
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType;
import org.thoughtcrime.securesms.logging.Log;
Expand All @@ -39,7 +38,6 @@
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.whispersystems.signalservice.internal.storage.protos.SignalStorage;

import java.util.Locale;

Expand Down Expand Up @@ -233,7 +231,7 @@ private void handleSuccess() {

if (Recipient.self().getProfileName().isEmpty() || !AvatarHelper.hasAvatar(activity, Recipient.self().getId())) {
final Intent main = new Intent(activity, MainActivity.class);
final Intent profile = EditProfileActivity.getIntent(activity, false);
final Intent profile = EditProfileActivity.getIntentForUserProfile(activity);

profile.putExtra("next_intent", main);
startActivity(profile);
Expand Down
Expand Up @@ -12,23 +12,34 @@

import org.thoughtcrime.securesms.BaseActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.DynamicRegistrationTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;

@SuppressLint("StaticFieldLeak")
public class EditProfileActivity extends BaseActionBarActivity implements EditProfileFragment.Controller {

public static final String NEXT_INTENT = "next_intent";
public static final String EXCLUDE_SYSTEM = "exclude_system";
public static final String DISPLAY_USERNAME = "display_username";
public static final String NEXT_BUTTON_TEXT = "next_button_text";
public static final String SHOW_TOOLBAR = "show_back_arrow";
public static final String NEXT_INTENT = "next_intent";
public static final String EXCLUDE_SYSTEM = "exclude_system";
public static final String DISPLAY_USERNAME = "display_username";
public static final String NEXT_BUTTON_TEXT = "next_button_text";
public static final String SHOW_TOOLBAR = "show_back_arrow";
public static final String GROUP_ID = "group_id";

private final DynamicTheme dynamicTheme = new DynamicRegistrationTheme();

public static @NonNull Intent getIntent(@NonNull Context context, boolean showToolbar) {
public static @NonNull Intent getIntentForUserProfile(@NonNull Context context) {
Intent intent = new Intent(context, EditProfileActivity.class);
intent.putExtra(EditProfileActivity.SHOW_TOOLBAR, showToolbar);
intent.putExtra(EditProfileActivity.SHOW_TOOLBAR, false);
return intent;
}

public static @NonNull Intent getIntentForGroupProfile(@NonNull Context context, @NonNull GroupId.Push groupId) {
Intent intent = new Intent(context, EditProfileActivity.class);
intent.putExtra(EditProfileActivity.SHOW_TOOLBAR, true);
intent.putExtra(EditProfileActivity.GROUP_ID, groupId.toString());
intent.putExtra(EditProfileActivity.NEXT_BUTTON_TEXT, R.string.save);
return intent;
}

Expand Down

0 comments on commit 5eb663a

Please sign in to comment.