Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f5594a0 authored by Walter Jang's avatar Walter Jang
Browse files

Add a name to raw contacts created to edit read-only contacts (E17)

This is a revert of the parts of ag/771915 (E5) where we changed
to moved to always showing all of the names.

Bug 24509375
Bug 23589603

Change-Id: Ief4773592233dc05b40bae8fb425d1c258d0b68f
parent cbd431df
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -21,17 +21,12 @@ import com.android.contacts.R;
import com.android.contacts.activities.CompactContactEditorActivity;
import com.android.contacts.activities.ContactEditorActivity;
import com.android.contacts.activities.ContactEditorBaseActivity;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.RawContactDelta;
import com.android.contacts.common.model.RawContactDeltaList;
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.detail.PhotoSelectionHandler;
import com.android.contacts.util.ContactPhotoUtils;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -114,7 +109,10 @@ public class CompactContactEditorFragment extends ContactEditorBaseFragment impl
        final CompactRawContactsEditorView editorView = getContent();
        editorView.setListener(this);
        editorView.setState(mState, getMaterialPalette(), mViewIdGenerator, mPhotoId,
                mHasNewContact, mIsUserProfile, mAccountWithDataSet);
                mReadOnlyDisplayName, mHasNewContact, mIsUserProfile, mAccountWithDataSet);
        if (mReadOnlyDisplayName != null) {
            mReadOnlyNameEditorView = editorView.getPrimaryNameEditorView();
        }

        // Set up the photo widget
        editorView.setPhotoListener(this);
+86 −20
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@ package com.android.contacts.editor;

import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -30,6 +32,7 @@ import android.widget.TextView;

import com.android.contacts.R;
import com.android.contacts.common.model.RawContactDelta;
import com.android.contacts.common.model.RawContactDeltaList;
import com.android.contacts.common.model.RawContactModifier;
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountType;
@@ -215,11 +218,66 @@ public class CompactKindSectionView extends LinearLayout {
        }
    }

    /**
     * Whether this is a name kind section view and all name fields (structured, phonetic,
     * and nicknames) are empty.
     */
    public boolean isEmptyName() {
        if (!StructuredName.CONTENT_ITEM_TYPE.equals(mKindSectionDataList.getMimeType())) {
            return false;
        }
        for (int i = 0; i < mEditors.getChildCount(); i++) {
            final View view = mEditors.getChildAt(i);
            if (view instanceof Editor) {
                final Editor editor = (Editor) view;
                if (!editor.isEmpty()) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Sets the given display name as the structured name as if the user input it, but
     * without informing editor listeners.
     */
    public void setName(String displayName) {
        if (!StructuredName.CONTENT_ITEM_TYPE.equals(mKindSectionDataList.getMimeType())) {
            return;
        }
        for (int i = 0; i < mEditors.getChildCount(); i++) {
            final View view = mEditors.getChildAt(i);
            if (view instanceof StructuredNameEditorView) {
                final StructuredNameEditorView editor = (StructuredNameEditorView) view;

                // Detach listeners since so we don't show suggested aggregations
                final Editor.EditorListener editorListener = editor.getEditorListener();
                editor.setEditorListener(null);

                editor.setDisplayName(displayName);

                // Reattach listeners
                editor.setEditorListener(editorListener);

                return;
            }
        }
    }

    public StructuredNameEditorView getPrimaryNameEditorView() {
        if (!StructuredName.CONTENT_ITEM_TYPE.equals(mKindSectionDataList.getMimeType())
            || mEditors.getChildCount() == 0) {
            return null;
        }
        return (StructuredNameEditorView) mEditors.getChildAt(0);
    }

    /**
     * Binds views for the given {@link KindSectionData} list.
     *
     * We create a structured name and phonetic name editor for each {@link DataKind} with a
     * {@link }StructuredName#CONTENT_ITEM_TYPE} mime type.  The number and order of editors are
     * {@link StructuredName#CONTENT_ITEM_TYPE} mime type.  The number and order of editors are
     * rendered as they are given to {@link #setState}.
     *
     * Empty name editors are never added and at least one structured name editor is always
@@ -262,9 +320,9 @@ public class CompactKindSectionView extends LinearLayout {
                        kindSectionData.getDataKind());
            } else {
                final Editor.EditorListener editorListener;
                if (kindSectionData.isNicknameDataKind()) {
                if (Nickname.CONTENT_ITEM_TYPE.equals(kindSectionData.getDataKind().mimeType)) {
                    editorListener = new OtherNameKindEditorListener();
                } else if (kindSectionData.isEventDataKind()) {
                } else if (Event.CONTENT_ITEM_TYPE.equals(kindSectionData.getDataKind().mimeType)) {
                    editorListener = new EventEditorListener();
                } else {
                    editorListener = new NonNameEditorListener();
@@ -386,7 +444,6 @@ public class CompactKindSectionView extends LinearLayout {
        if (isNameKindSection) {
            // The name kind section is always visible
            setVisibility(VISIBLE);

            updateEmptyNameEditors(shouldAnimate);
        } else if (isGroupKindSection) {
            // Check whether metadata has been bound for all group views
@@ -425,7 +482,7 @@ public class CompactKindSectionView extends LinearLayout {

        for (int i = 0; i < mEditors.getChildCount(); i++) {
            final View view = mEditors.getChildAt(i);
            if (!(view instanceof Editor)) continue; // Skip read-only names
            if (view instanceof Editor) {
                final Editor editor = (Editor) view;
                if (view instanceof StructuredNameEditorView) {
                    // We always show one empty structured name view
@@ -443,13 +500,21 @@ public class CompactKindSectionView extends LinearLayout {
                        isEmptyNameEditorVisible = true;
                    }
                } else {
                // For phonetic names and nicknames, which can't be added, just show or hide them
                    // Since we can't add phonetic names and nicknames, just show or hide them
                    if (mHideIfEmpty && editor.isEmpty()) {
                        hideView(view);
                    } else {
                        showView(view, /* shouldAnimate =*/ false); // Animation here causes jank
                    }
                }
            } else {
                // For read only names, only show them if we're not hiding empty views
                if (mHideIfEmpty) {
                    hideView(view);
                } else {
                    showView(view, shouldAnimate);
                }
            }
        }
    }

@@ -488,8 +553,9 @@ public class CompactKindSectionView extends LinearLayout {
            final RawContactDelta rawContactDelta =
                    mKindSectionDataList.get(0).getRawContactDelta();
            final ValuesDelta values = RawContactModifier.insertChild(rawContactDelta, dataKind);
            final Editor.EditorListener editorListener = mKindSectionDataList.get(0)
                    .isEventDataKind() ? new EventEditorListener() : new NonNameEditorListener();
            final String mimeType = mKindSectionDataList.getMimeType();
            final Editor.EditorListener editorListener = Event.CONTENT_ITEM_TYPE.equals(mimeType)
                    ? new EventEditorListener() : new NonNameEditorListener();
            final View view = addNonNameEditorView(rawContactDelta, dataKind, values,
                    editorListener);
            showView(view, shouldAnimate);
+29 −9
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ import java.util.TreeSet;
 */
public class CompactRawContactsEditorView extends LinearLayout implements View.OnClickListener {

    private static final String TAG = "CompactEditorView";
    static final String TAG = "CompactEditorView";

    private static final KindSectionDataMapEntryComparator
            KIND_SECTION_DATA_MAP_ENTRY_COMPARATOR = new KindSectionDataMapEntryComparator();
@@ -287,9 +287,9 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O
     */
    private static final class NameEditorComparator implements Comparator<KindSectionData> {

        private RawContactDeltaComparator mRawContactDeltaComparator;
        private MimeTypeComparator mMimeTypeComparator;
        private RawContactDelta mPrimaryRawContactDelta;
        private final RawContactDeltaComparator mRawContactDeltaComparator;
        private final MimeTypeComparator mMimeTypeComparator;
        private final RawContactDelta mPrimaryRawContactDelta;

        private NameEditorComparator(Context context, RawContactDelta primaryRawContactDelta) {
            mRawContactDeltaComparator = new RawContactDeltaComparator(context);
@@ -368,6 +368,7 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O
    private ViewIdGenerator mViewIdGenerator;
    private MaterialColorMapUtils.MaterialPalette mMaterialPalette;
    private long mPhotoId;
    private String mReadOnlyDisplayName;
    private boolean mHasNewContact;
    private boolean mIsUserProfile;
    private AccountWithDataSet mPrimaryAccount;
@@ -399,6 +400,7 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O

    private long mPhotoRawContactId;
    private ValuesDelta mPhotoValuesDelta;
    private StructuredNameEditorView mPrimaryNameEditorView;

    public CompactRawContactsEditorView(Context context) {
        super(context);
@@ -540,6 +542,10 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O
        return mPhotoRawContactId;
    }

    public StructuredNameEditorView getPrimaryNameEditorView() {
        return mPrimaryNameEditorView;
    }

    /**
     * Returns a data holder for every non-default/non-empty photo from each raw contact, whether
     * the raw contact is writable or not.
@@ -634,8 +640,8 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O

    public void setState(RawContactDeltaList rawContactDeltas,
            MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
            long photoId, boolean hasNewContact, boolean isUserProfile,
            AccountWithDataSet primaryAccount) {
            long photoId, String readOnlyDisplayName, boolean hasNewContact,
            boolean isUserProfile, AccountWithDataSet primaryAccount) {
        mKindSectionDataMap.clear();
        mKindSectionViews.removeAllViews();
        mMoreFields.setVisibility(View.VISIBLE);
@@ -643,6 +649,7 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O
        mMaterialPalette = materialPalette;
        mViewIdGenerator = viewIdGenerator;
        mPhotoId = photoId;
        mReadOnlyDisplayName = readOnlyDisplayName;
        mHasNewContact = hasNewContact;
        mIsUserProfile = isUserProfile;
        mPrimaryAccount = primaryAccount;
@@ -678,10 +685,10 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O
        addAccountInfo(rawContactDeltas);
        addPhotoView();
        addKindSectionViews();

        if (mIsExpanded) {
            showAllFields();
        if (mHasNewContact) {
            maybeCopyPrimaryDisplayName();
        }
        if (mIsExpanded) showAllFields();

        if (mListener != null) mListener.onEditorsBound();
    }
@@ -1021,6 +1028,19 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O
        return kindSectionView;
    }

    private void maybeCopyPrimaryDisplayName() {
        if (TextUtils.isEmpty(mReadOnlyDisplayName)) return;
        final List<CompactKindSectionView> kindSectionViews
                = mKindSectionViewsMap.get(StructuredName.CONTENT_ITEM_TYPE);
        if (kindSectionViews.isEmpty()) return;
        final CompactKindSectionView primaryNameKindSectionView = kindSectionViews.get(0);
        if (primaryNameKindSectionView.isEmptyName()) {
            vlog("name: using read only display name as primary name");
            primaryNameKindSectionView.setName(mReadOnlyDisplayName);
            mPrimaryNameEditorView = primaryNameKindSectionView.getPrimaryNameEditorView();
        }
    }

    private void showAllFields() {
        // Stop hiding empty editors and allow the user to enter values for all kinds now
        for (int i = 0; i < mKindSectionViews.getChildCount(); i++) {
+50 −4
Original line number Diff line number Diff line
@@ -363,6 +363,17 @@ abstract public class ContactEditorBaseFragment extends Fragment implements
    // Join Activity
    protected long mContactIdForJoin;

    //
    // Not saved/restored on rotates
    //

    // Used to pre-populate the editor with a display name when a user edits a read-only contact.
    protected String mReadOnlyDisplayName;

    // The name editor view for the new raw contact that was created so that the user can
    // edit a read-only contact (to which the new raw contact was joined)
    protected StructuredNameEditorView mReadOnlyNameEditorView;

    /**
     * The contact data loader listener.
     */
@@ -946,11 +957,41 @@ abstract public class ContactEditorBaseFragment extends Fragment implements
     * Return true if there are any edits to the current contact which need to
     * be saved.
     */
    protected boolean hasPendingChanges() {
    protected boolean hasPendingRawContactChanges() {
        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
        return RawContactModifier.hasChanges(mState, accountTypes);
    }

    /**
     * Determines if changes were made in the editor that need to be saved, while taking into
     * account that name changes are not real for read-only contacts.
     * See go/editing-read-only-contacts
     */
    protected boolean hasPendingChanges() {
        if (mReadOnlyNameEditorView == null || mReadOnlyDisplayName == null) {
            return hasPendingRawContactChanges();
        }
        // We created a new raw contact delta with a default display name.
        // We must test for pending changes while ignoring the default display name.
        final String displayName = mReadOnlyNameEditorView.getDisplayName();
        if (mReadOnlyDisplayName.equals(displayName)) {
            // The user did not modify the default display name, erase it and
            // check if the user made any other changes
            mReadOnlyNameEditorView.clearAllFields();
            if (hasPendingRawContactChanges()) {
                // Other changes were made to the aggregate contact, restore
                // the display name and proceed.
                mReadOnlyNameEditorView.setDisplayName(displayName);
                return true;
            } else {
                // No other changes were made to the aggregate contact. Don't add back
                // the displayName so that a "bogus" contact is not created.
                return false;
            }
        }
        return true;
    }

    /**
     * Whether editor inputs and the options menu should be enabled.
     */
@@ -1061,6 +1102,7 @@ abstract public class ContactEditorBaseFragment extends Fragment implements
            }
        }

        String readOnlyDisplayName = null;
        // Check for writable raw contacts.  If there are none, then we need to create one so user
        // can edit.  For the user profile case, there is already an editable contact.
        if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
@@ -1068,11 +1110,13 @@ abstract public class ContactEditorBaseFragment extends Fragment implements

            // This is potentially an asynchronous call and will add deltas to list.
            selectAccountAndCreateContact();

            readOnlyDisplayName = contact.getDisplayName();
        }

        // This also adds deltas to list.  If readOnlyDisplayName is null at this point it is
        // simply ignored later on by the editor.
        setStateForExistingContact(contact.isUserProfile(), mRawContacts);
        setStateForExistingContact(readOnlyDisplayName, contact.isUserProfile(), mRawContacts);
    }

    /**
@@ -1143,9 +1187,10 @@ abstract public class ContactEditorBaseFragment extends Fragment implements
    /**
     * Prepare {@link #mState} for an existing contact.
     */
    protected void setStateForExistingContact(boolean isUserProfile,
    protected void setStateForExistingContact(String readOnlyDisplayName, boolean isUserProfile,
            ImmutableList<RawContact> rawContacts) {
        setEnabled(true);
        mReadOnlyDisplayName = readOnlyDisplayName;

        mState.addAll(rawContacts.iterator());
        setIntentExtras(mIntentExtras);
@@ -1257,7 +1302,8 @@ abstract public class ContactEditorBaseFragment extends Fragment implements
            setStateForNewContact(newAccount, newAccountType, oldState, oldAccountType,
                    isEditingUserProfile());
            if (mIsEdit) {
                setStateForExistingContact(isEditingUserProfile(), mRawContacts);
                setStateForExistingContact(mReadOnlyDisplayName, isEditingUserProfile(),
                        mRawContacts);
            }
        }
    }
+0 −12
Original line number Diff line number Diff line
@@ -97,18 +97,6 @@ public final class KindSectionData {
        return mDataKind;
    }

    public boolean isNameDataKind() {
        return StructuredName.CONTENT_ITEM_TYPE.equals(mDataKind.mimeType);
    }

    public boolean isNicknameDataKind() {
        return Nickname.CONTENT_ITEM_TYPE.equals(mDataKind.mimeType);
    }

    public boolean isEventDataKind() {
        return Event.CONTENT_ITEM_TYPE.equals(mDataKind.mimeType);
    }

    public RawContactDelta getRawContactDelta() {
        return mRawContactDelta;
    }
Loading