diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org')
17 files changed, 533 insertions, 224 deletions
| diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 8fdfb35cb..ed4cf5b8a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -123,7 +123,6 @@ public class CreateKeyEmailFragment extends Fragment {          if (mAdditionalEmailModels == null) {              mAdditionalEmailModels = new ArrayList<>();          } -          if (mEmailAdapter == null) {              mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() {                  @Override @@ -136,6 +135,9 @@ public class CreateKeyEmailFragment extends Fragment {                  mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails);              }          } +        if (mAdditionalEmailModels.isEmpty() && mCreateKeyActivity.mAdditionalEmails != null) { +            mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); +        }          mEmailsRecyclerView.setAdapter(mEmailAdapter); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java index 32173edf7..3379e0a6d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java @@ -21,7 +21,6 @@ import android.app.Activity;  import android.content.Context;  import android.os.Bundle;  import android.support.v4.app.Fragment; -import android.text.Editable;  import android.text.method.HideReturnsTransformationMethod;  import android.text.method.PasswordTransformationMethod;  import android.view.LayoutInflater; @@ -37,9 +36,6 @@ import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;  import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;  import org.sufficientlysecure.keychain.util.Passphrase; -import java.util.ArrayList; -import java.util.Arrays; -  public class CreateKeyPassphraseFragment extends Fragment {      // view @@ -111,8 +107,8 @@ public class CreateKeyPassphraseFragment extends Fragment {          // initial values          // TODO: using String here is unsafe...          if (mCreateKeyActivity.mPassphrase != null) { -            mPassphraseEdit.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); -            mPassphraseEditAgain.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); +            mPassphraseEdit.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray())); +            mPassphraseEditAgain.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray()));          }          mPassphraseEdit.requestFocus(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index 766e65e8b..6c1902af1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -240,7 +240,7 @@ public class DecryptFilesFragment extends DecryptFragment {                              }                              case KeychainIntentService.ACTION_DECRYPT_VERIFY: {                                  // display signature result in activity -                                onResult(pgpResult); +                                loadVerifyResult(pgpResult);                                  if (mDeleteAfter.isChecked()) {                                      // Create and show dialog to delete original file @@ -308,4 +308,8 @@ public class DecryptFilesFragment extends DecryptFragment {          }      } +    @Override +    protected void onVerifyLoaded(boolean verified) { + +    }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 33209be86..651b56ab0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -17,26 +17,49 @@  package org.sufficientlysecure.keychain.ui; +import java.util.ArrayList; +  import android.content.Intent; +import android.database.Cursor; +import android.net.Uri;  import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.util.Log;  import android.view.View;  import android.widget.ImageView;  import android.widget.LinearLayout;  import android.widget.TextView;  import org.openintents.openpgp.OpenPgpSignatureResult; +import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;  import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; +import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult;  import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;  import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.ServiceProgressHandler;  import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;  import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;  import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; +import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify.Style; +import org.sufficientlysecure.keychain.util.Preferences; + -public abstract class DecryptFragment extends CryptoOperationFragment { -    private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006; +public abstract class DecryptFragment extends CryptoOperationFragment implements +        LoaderManager.LoaderCallbacks<Cursor> { -    protected long mSignatureKeyId = 0; +    public static final int LOADER_ID_UNIFIED = 0;      protected LinearLayout mResultLayout; @@ -46,155 +69,119 @@ public abstract class DecryptFragment extends CryptoOperationFragment {      protected TextView mSignatureText;      protected View mSignatureLayout; -    protected View mSignatureDivider1; -    protected View mSignatureDivider2;      protected TextView mSignatureName;      protected TextView mSignatureEmail;      protected TextView mSignatureAction; +    private OpenPgpSignatureResult mSignatureResult; +      @Override -    public void onActivityCreated(Bundle savedInstanceState) { -        super.onActivityCreated(savedInstanceState); +    public void onViewCreated(View view, Bundle savedInstanceState) { +        super.onViewCreated(view, savedInstanceState); -        mResultLayout = (LinearLayout) getView().findViewById(R.id.result_main_layout); +        // NOTE: These views are inside the activity! +        mResultLayout = (LinearLayout) getActivity().findViewById(R.id.result_main_layout);          mResultLayout.setVisibility(View.GONE); -        mEncryptionIcon = (ImageView) getView().findViewById(R.id.result_encryption_icon); -        mEncryptionText = (TextView) getView().findViewById(R.id.result_encryption_text); -        mSignatureIcon = (ImageView) getView().findViewById(R.id.result_signature_icon); -        mSignatureText = (TextView) getView().findViewById(R.id.result_signature_text); -        mSignatureLayout = getView().findViewById(R.id.result_signature_layout); -        mSignatureDivider1 = getView().findViewById(R.id.result_signature_divider1); -        mSignatureDivider2 = getView().findViewById(R.id.result_signature_divider2); -        mSignatureName = (TextView) getView().findViewById(R.id.result_signature_name); -        mSignatureEmail = (TextView) getView().findViewById(R.id.result_signature_email); -        mSignatureAction = (TextView) getView().findViewById(R.id.result_signature_action); +        mEncryptionIcon = (ImageView) getActivity().findViewById(R.id.result_encryption_icon); +        mEncryptionText = (TextView) getActivity().findViewById(R.id.result_encryption_text); +        mSignatureIcon = (ImageView) getActivity().findViewById(R.id.result_signature_icon); +        mSignatureText = (TextView) getActivity().findViewById(R.id.result_signature_text); +        mSignatureLayout = getActivity().findViewById(R.id.result_signature_layout); +        mSignatureName = (TextView) getActivity().findViewById(R.id.result_signature_name); +        mSignatureEmail = (TextView) getActivity().findViewById(R.id.result_signature_email); +        mSignatureAction = (TextView) getActivity().findViewById(R.id.result_signature_action);      }      private void lookupUnknownKey(long unknownKeyId) { -        Intent intent = new Intent(getActivity(), ImportKeysActivity.class); -        intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER); -        intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, unknownKeyId); -        startActivityForResult(intent, RESULT_CODE_LOOKUP_KEY); -    } - -    private void showKey(long keyId) { -        Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class); -        viewKeyIntent.setData(KeychainContract.KeyRings -                .buildGenericKeyRingUri(keyId)); -        startActivity(viewKeyIntent); -    } -    /** -     * -     * @return returns false if signature is invalid, key is revoked or expired. -     */ -    protected boolean onResult(DecryptVerifyResult decryptVerifyResult) { -        final OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); +        // Message is received after importing is done in KeychainIntentService +        ServiceProgressHandler serviceHandler = new ServiceProgressHandler(getActivity()) { +            public void handleMessage(Message message) { +                // handle messages by standard KeychainIntentServiceHandler first +                super.handleMessage(message); -        boolean valid = false; +                if (message.arg1 == MessageStatus.OKAY.ordinal()) { +                    // get returned data bundle +                    Bundle returnData = message.getData(); -        mSignatureKeyId = 0; -        mResultLayout.setVisibility(View.VISIBLE); -        if (signatureResult != null) { -            mSignatureKeyId = signatureResult.getKeyId(); - -            String userId = signatureResult.getPrimaryUserId(); -            KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); -            if (userIdSplit.name != null) { -                mSignatureName.setText(userIdSplit.name); -            } else { -                mSignatureName.setText(R.string.user_id_no_name); -            } -            if (userIdSplit.email != null) { -                mSignatureEmail.setText(userIdSplit.email); -            } else { -                mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(getActivity(), mSignatureKeyId)); -            } +                    if (returnData == null) { +                        return; +                    } -            if (signatureResult.isSignatureOnly()) { -                mEncryptionText.setText(R.string.decrypt_result_not_encrypted); -                KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED); -            } else { -                mEncryptionText.setText(R.string.decrypt_result_encrypted); -                KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED); -            } +                    final ImportKeyResult result = +                            returnData.getParcelable(OperationResult.EXTRA_RESULT); -            switch (signatureResult.getStatus()) { -                case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { -                    mSignatureText.setText(R.string.decrypt_result_signature_certified); -                    KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED); +                    // if (!result.success()) { +                        result.createNotify(getActivity()).show(); +                    // } -                    setSignatureLayoutVisibility(View.VISIBLE); -                    setShowAction(mSignatureKeyId); +                    getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, DecryptFragment.this); -                    valid = true; -                    break;                  } +            } +        }; -                case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { -                    mSignatureText.setText(R.string.decrypt_result_signature_uncertified); -                    KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNVERIFIED); +        // fill values for this action +        Bundle data = new Bundle(); -                    setSignatureLayoutVisibility(View.VISIBLE); -                    setShowAction(mSignatureKeyId); +        // search config +        { +            Preferences prefs = Preferences.getPreferences(getActivity()); +            Preferences.CloudSearchPrefs cloudPrefs = +                    new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver()); +            data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver); +        } -                    valid = true; -                    break; -                } +        { +            ParcelableKeyRing keyEntry = new ParcelableKeyRing(null, +                    KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null); +            ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>(); +            selectedEntries.add(keyEntry); -                case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: { -                    mSignatureText.setText(R.string.decrypt_result_signature_missing_key); -                    KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY); - -                    setSignatureLayoutVisibility(View.VISIBLE); -                    mSignatureAction.setText(R.string.decrypt_result_action_Lookup); -                    mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_file_download_grey_24dp, 0); -                    mSignatureLayout.setOnClickListener(new View.OnClickListener() { -                        @Override -                        public void onClick(View v) { -                            lookupUnknownKey(mSignatureKeyId); -                        } -                    }); - -                    valid = true; -                    break; -                } +            data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries); +        } -                case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: { -                    mSignatureText.setText(R.string.decrypt_result_signature_expired_key); -                    KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.EXPIRED); +        // Send all information needed to service to query keys in other thread +        Intent intent = new Intent(getActivity(), KeychainIntentService.class); +        intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING); +        intent.putExtra(KeychainIntentService.EXTRA_DATA, data); -                    setSignatureLayoutVisibility(View.VISIBLE); -                    setShowAction(mSignatureKeyId); +        // Create a new Messenger for the communication back +        Messenger messenger = new Messenger(serviceHandler); +        intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); -                    valid = false; -                    break; -                } +        getActivity().startService(intent); -                case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: { -                    mSignatureText.setText(R.string.decrypt_result_signature_revoked_key); -                    KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.REVOKED); +    } -                    setSignatureLayoutVisibility(View.VISIBLE); -                    setShowAction(mSignatureKeyId); +    private void showKey(long keyId) { +        try { -                    valid = false; -                    break; -                } +            Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class); +            long masterKeyId = new ProviderHelper(getActivity()).getCachedPublicKeyRing( +                    KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId) +            ).getMasterKeyId(); +            viewKeyIntent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); +            startActivity(viewKeyIntent); + +        } catch (PgpKeyNotFoundException e) { +            Notify.create(getActivity(), R.string.error_key_not_found, Style.ERROR); +        } +    } + +    /** +     * @return returns false if signature is invalid, key is revoked or expired. +     */ +    protected void loadVerifyResult(DecryptVerifyResult decryptVerifyResult) { -                case OpenPgpSignatureResult.SIGNATURE_ERROR: { -                    mSignatureText.setText(R.string.decrypt_result_invalid_signature); -                    KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID); +        mSignatureResult = decryptVerifyResult.getSignatureResult(); +        mResultLayout.setVisibility(View.VISIBLE); -                    setSignatureLayoutVisibility(View.GONE); +        // unsigned data +        if (mSignatureResult == null) { -                    valid = false; -                    break; -                } -            } -        } else {              setSignatureLayoutVisibility(View.GONE);              mSignatureText.setText(R.string.decrypt_result_no_signature); @@ -202,16 +189,27 @@ public abstract class DecryptFragment extends CryptoOperationFragment {              mEncryptionText.setText(R.string.decrypt_result_encrypted);              KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED); -            valid = true; +            getLoaderManager().destroyLoader(LOADER_ID_UNIFIED); + +            onVerifyLoaded(true); + +            return; +        } + +        if (mSignatureResult.isSignatureOnly()) { +            mEncryptionText.setText(R.string.decrypt_result_not_encrypted); +            KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED); +        } else { +            mEncryptionText.setText(R.string.decrypt_result_encrypted); +            KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);          } -        return valid; +        getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this); +      }      private void setSignatureLayoutVisibility(int visibility) {          mSignatureLayout.setVisibility(visibility); -        mSignatureDivider1.setVisibility(visibility); -        mSignatureDivider2.setVisibility(visibility);      }      private void setShowAction(final long signatureKeyId) { @@ -225,4 +223,177 @@ public abstract class DecryptFragment extends CryptoOperationFragment {          });      } +    // These are the rows that we will retrieve. +    static final String[] UNIFIED_PROJECTION = new String[]{ +            KeychainContract.KeyRings._ID, +            KeychainContract.KeyRings.MASTER_KEY_ID, +            KeychainContract.KeyRings.USER_ID, +            KeychainContract.KeyRings.IS_REVOKED, +            KeychainContract.KeyRings.IS_EXPIRED, +            KeychainContract.KeyRings.VERIFIED, +    }; + +    @SuppressWarnings("unused") +    static final int INDEX_MASTER_KEY_ID = 1; +    static final int INDEX_USER_ID = 2; +    static final int INDEX_IS_REVOKED = 3; +    static final int INDEX_IS_EXPIRED = 4; +    static final int INDEX_VERIFIED = 5; + +    @Override +    public Loader<Cursor> onCreateLoader(int id, Bundle args) { +        if (id != LOADER_ID_UNIFIED) { +            return null; +        } + +        Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( +                mSignatureResult.getKeyId()); +        return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null); +    } + +    @Override +    public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + +        if (loader.getId() != LOADER_ID_UNIFIED) { +            return; +        } + +        // If the key is unknown, show it as such +        if (data.getCount() == 0 || !data.moveToFirst()) { +            showUnknownKeyStatus(); +            return; +        } + +        long signatureKeyId = mSignatureResult.getKeyId(); + +        String userId = data.getString(INDEX_USER_ID); +        KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); +        if (userIdSplit.name != null) { +            mSignatureName.setText(userIdSplit.name); +        } else { +            mSignatureName.setText(R.string.user_id_no_name); +        } +        if (userIdSplit.email != null) { +            mSignatureEmail.setText(userIdSplit.email); +        } else { +            mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix( +                    getActivity(), mSignatureResult.getKeyId())); +        } + +        boolean isRevoked = data.getInt(INDEX_IS_REVOKED) != 0; +        boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0; +        boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; + +        if (isRevoked) { +            mSignatureText.setText(R.string.decrypt_result_signature_revoked_key); +            KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.REVOKED); + +            setSignatureLayoutVisibility(View.VISIBLE); +            setShowAction(signatureKeyId); + +            onVerifyLoaded(false); + +        } else if (isExpired) { +            mSignatureText.setText(R.string.decrypt_result_signature_expired_key); +            KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.EXPIRED); + +            setSignatureLayoutVisibility(View.VISIBLE); +            setShowAction(signatureKeyId); + +            onVerifyLoaded(true); + +        } else if (isVerified) { +            mSignatureText.setText(R.string.decrypt_result_signature_certified); +            KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED); + +            setSignatureLayoutVisibility(View.VISIBLE); +            setShowAction(signatureKeyId); + +            onVerifyLoaded(true); + +        } else { +            mSignatureText.setText(R.string.decrypt_result_signature_uncertified); +            KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNVERIFIED); + +            setSignatureLayoutVisibility(View.VISIBLE); +            setShowAction(signatureKeyId); + +            onVerifyLoaded(true); +        } + +    } + +    @Override +    public void onLoaderReset(Loader<Cursor> loader) { + +        if (loader.getId() != LOADER_ID_UNIFIED) { +            return; +        } + +        setSignatureLayoutVisibility(View.GONE); + +    } + +    private void showUnknownKeyStatus() { + +        final long signatureKeyId = mSignatureResult.getKeyId(); + +        int result = mSignatureResult.getStatus(); +        if (result != OpenPgpSignatureResult.SIGNATURE_KEY_MISSING +                && result != OpenPgpSignatureResult.SIGNATURE_ERROR) { +            Log.e(Constants.TAG, "got missing status for non-missing key, shouldn't happen!"); +        } + +        String userId = mSignatureResult.getPrimaryUserId(); +        KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); +        if (userIdSplit.name != null) { +            mSignatureName.setText(userIdSplit.name); +        } else { +            mSignatureName.setText(R.string.user_id_no_name); +        } +        if (userIdSplit.email != null) { +            mSignatureEmail.setText(userIdSplit.email); +        } else { +            mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix( +                    getActivity(), mSignatureResult.getKeyId())); +        } + +        switch (mSignatureResult.getStatus()) { + +            case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: { +                mSignatureText.setText(R.string.decrypt_result_signature_missing_key); +                KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY); + +                setSignatureLayoutVisibility(View.VISIBLE); +                mSignatureAction.setText(R.string.decrypt_result_action_Lookup); +                mSignatureAction +                        .setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_file_download_grey_24dp, 0); +                mSignatureLayout.setOnClickListener(new View.OnClickListener() { +                    @Override +                    public void onClick(View v) { +                        lookupUnknownKey(signatureKeyId); +                    } +                }); + +                onVerifyLoaded(true); + +                break; +            } + +            case OpenPgpSignatureResult.SIGNATURE_ERROR: { +                mSignatureText.setText(R.string.decrypt_result_invalid_signature); +                KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID); + +                setSignatureLayoutVisibility(View.GONE); + +                onVerifyLoaded(false); +                break; +            } + +        } + +    } + +    protected abstract void onVerifyLoaded(boolean verified); +  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java index 9c6c89c43..6f576a112 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -23,6 +23,9 @@ import android.os.Bundle;  import android.os.Message;  import android.os.Messenger;  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; @@ -39,7 +42,6 @@ import org.sufficientlysecure.keychain.service.ServiceProgressHandler;  import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;  import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;  import org.sufficientlysecure.keychain.ui.util.Notify; -import org.sufficientlysecure.keychain.util.Log;  import org.sufficientlysecure.keychain.util.ShareHelper;  import java.io.UnsupportedEncodingException; @@ -54,6 +56,7 @@ public class DecryptTextFragment extends DecryptFragment {      // model      private String mCiphertext; +    private boolean mShowMenuOptions = false;      /**       * Creates new instance of this fragment @@ -79,22 +82,6 @@ public class DecryptTextFragment extends DecryptFragment {          mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid);          mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext); -        View vShareButton = view.findViewById(R.id.action_decrypt_share_plaintext); -        vShareButton.setOnClickListener(new View.OnClickListener() { -            @Override -            public void onClick(View v) { -                startActivity(sendWithChooserExcludingEncrypt(mText.getText().toString())); -            } -        }); - -        View vCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext); -        vCopyButton.setOnClickListener(new View.OnClickListener() { -            @Override -            public void onClick(View v) { -                copyToClipboard(mText.getText().toString()); -            } -        }); -          Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button);          vInvalidButton.setOnClickListener(new View.OnClickListener() {              @Override @@ -110,9 +97,9 @@ public class DecryptTextFragment extends DecryptFragment {      /**       * Create Intent Chooser but exclude decrypt activites       */ -    private Intent sendWithChooserExcludingEncrypt(String text) { +    private Intent sendWithChooserExcludingDecrypt(String text) {          Intent prototype = createSendIntent(text); -        String title = getString(R.string.title_share_file); +        String title = getString(R.string.title_share_message);          // we don't want to decrypt the decrypted, no inception ;)          String[] blacklist = new String[]{ @@ -139,6 +126,8 @@ public class DecryptTextFragment extends DecryptFragment {      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState); +        setHasOptionsMenu(true); +          String ciphertext = getArguments().getString(ARG_CIPHERTEXT);          if (ciphertext != null) {              mCiphertext = ciphertext; @@ -147,6 +136,33 @@ public class DecryptTextFragment extends DecryptFragment {      }      @Override +    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { +        super.onCreateOptionsMenu(menu, inflater); +        if (mShowMenuOptions) { +            inflater.inflate(R.menu.decrypt_menu, menu); +        } +    } + +    @Override +    public boolean onOptionsItemSelected(MenuItem item) { +        switch (item.getItemId()) { +            case R.id.decrypt_share: { +                startActivity(sendWithChooserExcludingDecrypt(mText.getText().toString())); +                break; +            } +            case R.id.decrypt_copy: { +                copyToClipboard(mText.getText().toString()); +                break; +            } +            default: { +                return super.onOptionsItemSelected(item); +            } +        } + +        return true; +    } + +    @Override      protected void cryptoOperation(CryptoInputParcel cryptoInput) {          // Send all information needed to service to decrypt in other thread          Intent intent = new Intent(getActivity(), KeychainIntentService.class); @@ -206,15 +222,8 @@ public class DecryptTextFragment extends DecryptFragment {                          pgpResult.createNotify(getActivity()).show();                          // display signature result in activity -                        boolean valid = onResult(pgpResult); +                        loadVerifyResult(pgpResult); -                        if (valid) { -                            mInvalidLayout.setVisibility(View.GONE); -                            mValidLayout.setVisibility(View.VISIBLE); -                        } else { -                            mInvalidLayout.setVisibility(View.VISIBLE); -                            mValidLayout.setVisibility(View.GONE); -                        }                      } else {                          pgpResult.createNotify(getActivity()).show();                          // TODO: show also invalid layout with different text? @@ -234,4 +243,19 @@ public class DecryptTextFragment extends DecryptFragment {          getActivity().startService(intent);      } +    @Override +    protected void onVerifyLoaded(boolean verified) { + +        mShowMenuOptions = verified; +        getActivity().supportInvalidateOptionsMenu(); + +        if (verified) { +            mInvalidLayout.setVisibility(View.GONE); +            mValidLayout.setVisibility(View.VISIBLE); +        } else { +            mInvalidLayout.setVisibility(View.VISIBLE); +            mValidLayout.setVisibility(View.GONE); +        } + +    }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 03ab48e23..dd6dd6594 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -98,23 +98,20 @@ public class EncryptTextActivity extends BaseActivity implements                      // handle like normal text encryption, override action and extras to later                      // executeServiceMethod ACTION_ENCRYPT_TEXT in main actions                      extras.putString(EXTRA_TEXT, sharedText); -                    action = ACTION_ENCRYPT_TEXT;                  }              }          }          String textData = extras.getString(EXTRA_TEXT); -        if (ACTION_ENCRYPT_TEXT.equals(action) && textData == null) { -            Log.e(Constants.TAG, "Include the extra 'text' in your Intent!"); -            return; +        if (textData == null) { +            textData = "";          }          // preselect keys given by intent          long mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID);          long[] mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); -          if (savedInstanceState == null) {              FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java index 5fa3edba4..f571ba1e6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -1,6 +1,7 @@  /*   * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>   * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com> + * Copyright (C) 2015 Kai Jiang <jiangkai@gmail.com>   *   * This program is free software: you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -20,36 +21,98 @@ package org.sufficientlysecure.keychain.ui;  import android.content.Intent;  import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.AdapterView; + +import com.mikepenz.community_material_typeface_library.CommunityMaterial; +import com.mikepenz.google_material_typeface_library.GoogleMaterial; +import com.mikepenz.iconics.typeface.FontAwesome; +import com.mikepenz.materialdrawer.Drawer; +import com.mikepenz.materialdrawer.model.PrimaryDrawerItem; +import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;  import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.operations.results.OperationResult;  import org.sufficientlysecure.keychain.remote.ui.AppsListFragment; -import org.sufficientlysecure.keychain.util.Preferences;  import org.sufficientlysecure.keychain.util.FabContainer; +import org.sufficientlysecure.keychain.util.Preferences; -import it.neokree.materialnavigationdrawer.MaterialNavigationDrawer; +public class MainActivity extends AppCompatActivity implements FabContainer { -public class MainActivity extends MaterialNavigationDrawer implements FabContainer { +    public Drawer.Result result; -    @Override -    public void init(Bundle savedInstanceState) { -        // don't open drawer on first run -        disableLearningPattern(); +    private KeyListFragment mKeyListFragment ; +    private AppsListFragment mAppsListFragment; +    private EncryptDecryptOverviewFragment mEncryptDecryptOverviewFragment; +    private Fragment mLastUsedFragment; +    private Toolbar mToolbar; -//        addMultiPaneSupport(); +    @Override +    public void onCreate(Bundle savedInstanceState) { +        super.onCreate(savedInstanceState); +        setContentView(R.layout.main_activity); -        // set the header image -        // create and set the header -        setDrawerHeaderImage(R.drawable.drawer_header); +        //initialize FragmentLayout with KeyListFragment at first +        Fragment mainFragment = new KeyListFragment(); +        FragmentManager fm = getSupportFragmentManager(); +        FragmentTransaction transaction = fm.beginTransaction(); +        transaction.replace(R.id.main_fragment_container, mainFragment); +        transaction.commit(); -        // create sections -        addSection(newSection(getString(R.string.nav_keys), R.drawable.ic_vpn_key_black_24dp, new KeyListFragment())); -        addSection(newSection(getString(R.string.nav_encrypt_decrypt), R.drawable.ic_lock_black_24dp, new EncryptDecryptOverviewFragment())); -        addSection(newSection(getString(R.string.title_api_registered_apps), R.drawable.ic_apps_black_24dp, new AppsListFragment())); +        mToolbar = (Toolbar) findViewById(R.id.toolbar); +        mToolbar.setTitle(R.string.app_name); +        setSupportActionBar(mToolbar); -        // create bottom section -        addBottomSection(newSection(getString(R.string.menu_preferences), R.drawable.ic_settings_black_24dp, new Intent(this, SettingsActivity.class))); -        addBottomSection(newSection(getString(R.string.menu_help), R.drawable.ic_help_black_24dp, new Intent(this, HelpActivity.class))); +        result = new Drawer() +                .withActivity(this) +                .withHeader(R.layout.main_drawer_header) +                .withToolbar(mToolbar) +                .addDrawerItems( +                        new PrimaryDrawerItem().withName(R.string.nav_keys).withIcon(CommunityMaterial.Icon.cmd_key).withIdentifier(1).withCheckable(false), +                        new PrimaryDrawerItem().withName(R.string.nav_encrypt_decrypt).withIcon(FontAwesome.Icon.faw_lock).withIdentifier(2).withCheckable(false), +                        new PrimaryDrawerItem().withName(R.string.title_api_registered_apps).withIcon(CommunityMaterial.Icon.cmd_apps).withIdentifier(3).withCheckable(false) +                ) +                .addStickyDrawerItems( +                        // display and stick on bottom of drawer +                        new PrimaryDrawerItem().withName(R.string.menu_preferences).withIcon(GoogleMaterial.Icon.gmd_settings).withIdentifier(4).withCheckable(false), +                        new PrimaryDrawerItem().withName(R.string.menu_help).withIcon(CommunityMaterial.Icon.cmd_help_circle).withIdentifier(5).withCheckable(false) +                ) +                .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() { +                    @Override +                    public void onItemClick(AdapterView<?> parent, View view, int position, long id, IDrawerItem drawerItem) { +                        if (drawerItem != null) { +                            Intent intent = null; +                            switch(drawerItem.getIdentifier()) { +                                case 1: +                                    onKeysSelected(); +                                    break; +                                case 2: +                                    onEnDecryptSelected(); +                                    break; +                                case 3: +                                    onAppsSelected(); +                                    break; +                                case 4: +                                    intent = new Intent(MainActivity.this, SettingsActivity.class); +                                    break; +                                case 5: +                                    intent = new Intent(MainActivity.this, HelpActivity.class); +                                    break; +                            } +                            if (intent != null) { +                                MainActivity.this.startActivity(intent); +                            } +                        } +                    } +                }) +                .withSelectedItem(-1) +                .withSavedInstance(savedInstanceState) +                .build();          // if this is the first time show first time activity          Preferences prefs = Preferences.getPreferences(this); @@ -69,9 +132,83 @@ public class MainActivity extends MaterialNavigationDrawer implements FabContain          }      } +    private void clearFragments() { +        mKeyListFragment = null; +        mAppsListFragment = null; +        mEncryptDecryptOverviewFragment = null; + +        getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); +    } + +    private void setFragment(Fragment fragment) { +        setFragment(fragment, true); +    } + +    private void setFragment(Fragment fragment, boolean addToBackStack) { +        this.mLastUsedFragment = fragment; +        FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); +        ft.replace(R.id.main_fragment_container, fragment); +        if (addToBackStack) { +            ft.addToBackStack(null); +        } +        ft.commit(); +    } + +    private boolean onKeysSelected() { +        mToolbar.setTitle(R.string.app_name); +        clearFragments(); + +        if (mKeyListFragment == null) { +            mKeyListFragment = new KeyListFragment(); +        } + +        setFragment(mKeyListFragment, false); +        return true; +    } + +    private boolean onEnDecryptSelected() { +        mToolbar.setTitle(R.string.nav_encrypt_decrypt); +        clearFragments(); +        if (mEncryptDecryptOverviewFragment == null) { +            mEncryptDecryptOverviewFragment = new EncryptDecryptOverviewFragment(); +        } + +        setFragment(mEncryptDecryptOverviewFragment); +        return true; +    } + +    private boolean onAppsSelected() { +        mToolbar.setTitle(R.string.nav_apps); +        clearFragments(); +        if (mAppsListFragment == null) { +            mAppsListFragment = new AppsListFragment(); +        } + +        setFragment(mAppsListFragment); +        return true; +    } + +    @Override +    protected void onSaveInstanceState(Bundle outState) { +        //add the values which need to be saved from the drawer to the bundle +        outState = result.saveInstanceState(outState); +        super.onSaveInstanceState(outState); +    } + +    @Override +    public void onBackPressed(){ +        //handle the back press :D close the drawer first and if the drawer is closed close the activity +        if (result != null && result.isDrawerOpen()) { +            result.closeDrawer(); +        } else { +            super.onBackPressed(); +        } +    } +      @Override      public void fabMoveUp(int height) { -        Object fragment = getCurrentSection().getTargetFragment(); +        Object fragment = getSupportFragmentManager() +                .findFragmentById(R.id.main_fragment_container);          if (fragment instanceof FabContainer) {              ((FabContainer) fragment).fabMoveUp(height);          } @@ -79,7 +216,8 @@ public class MainActivity extends MaterialNavigationDrawer implements FabContain      @Override      public void fabRestorePosition() { -        Object fragment = getCurrentSection().getTargetFragment(); +        Object fragment = getSupportFragmentManager() +                .findFragmentById(R.id.main_fragment_container);          if (fragment instanceof FabContainer) {              ((FabContainer) fragment).fabRestorePosition();          } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java index 963e77fe9..7b911da96 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java @@ -21,7 +21,7 @@ import android.app.Activity;  import android.os.Bundle;  import android.support.v4.app.Fragment;  import android.support.v4.app.FragmentPagerAdapter; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity;  import java.util.ArrayList; @@ -41,7 +41,7 @@ public class PagerTabStripAdapter extends FragmentPagerAdapter {          }      } -    public PagerTabStripAdapter(ActionBarActivity activity) { +    public PagerTabStripAdapter(AppCompatActivity activity) {          super(activity.getSupportFragmentManager());          mActivity = activity;      } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java index 44afed351..a1f00599c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java @@ -24,7 +24,7 @@ import android.support.v4.app.FragmentStatePagerAdapter;  import android.support.v4.app.FragmentTransaction;  import android.support.v4.view.ViewPager;  import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity;  import java.util.ArrayList; @@ -45,7 +45,7 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.          }      } -    public TabsAdapter(ActionBarActivity activity, ViewPager pager) { +    public TabsAdapter(AppCompatActivity activity, ViewPager pager) {          super(activity.getSupportFragmentManager());          mContext = activity;          mActionBar = activity.getSupportActionBar(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java index 07d2ef8c0..0e752881f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java @@ -20,7 +20,7 @@ package org.sufficientlysecure.keychain.ui.base;  import android.app.Activity;  import android.os.Bundle;  import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity;  import android.support.v7.widget.Toolbar;  import android.view.Gravity;  import android.view.LayoutInflater; @@ -33,7 +33,7 @@ import org.sufficientlysecure.keychain.R;  /**   * Setups Toolbar   */ -public abstract class BaseActivity extends ActionBarActivity { +public abstract class BaseActivity extends AppCompatActivity {      protected Toolbar mToolbar;      protected View mStatusBar; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java index e21c5d510..e55f6b1ad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java @@ -17,9 +17,8 @@  package org.sufficientlysecure.keychain.ui.widget; -import android.annotation.TargetApi;  import android.content.Context; -import android.os.Build; +import android.support.v7.widget.AppCompatAutoCompleteTextView;  import android.text.Editable;  import android.text.InputType;  import android.text.TextWatcher; @@ -27,14 +26,13 @@ import android.util.AttributeSet;  import android.util.Patterns;  import android.view.inputmethod.EditorInfo;  import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView;  import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.util.ContactHelper;  import java.util.regex.Matcher; -public class EmailEditText extends AutoCompleteTextView { +public class EmailEditText extends AppCompatAutoCompleteTextView {      public EmailEditText(Context context) {          super(context); @@ -51,12 +49,6 @@ public class EmailEditText extends AutoCompleteTextView {          init();      } -    @TargetApi(Build.VERSION_CODES.LOLLIPOP) -    public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { -        super(context, attrs, defStyleAttr, defStyleRes); -        init(); -    } -      private void init() {          setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);          reenableKeyboardSuggestions(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index b2dfb2493..3d2e8b9df 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -108,9 +108,8 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView      protected void onAttachedToWindow() {          super.onAttachedToWindow(); -        mLoaderManager = ((FragmentActivity) getContext()).getSupportLoaderManager(); -          if (getContext() instanceof FragmentActivity) { +            mLoaderManager = ((FragmentActivity) getContext()).getSupportLoaderManager();              mLoaderManager.initLoader(hashCode(), null, this);          } else {              Log.e(Constants.TAG, "EncryptKeyCompletionView must be attached to a FragmentActivity, this is " + getContext().getClass()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index 2c75c3a7d..fc5ecd76a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -24,7 +24,7 @@ import android.support.v4.app.FragmentActivity;  import android.support.v4.app.LoaderManager;  import android.support.v4.content.Loader;  import android.support.v4.widget.CursorAdapter; -import android.support.v7.internal.widget.TintSpinner; +import android.support.v7.widget.AppCompatSpinner;  import android.text.format.DateFormat;  import android.util.AttributeSet;  import android.view.View; @@ -46,10 +46,10 @@ import java.util.Date;  import java.util.TimeZone;  /** - * Use TintSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon. + * Use AppCompatSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon.   * Related: http://stackoverflow.com/a/27713090   */ -public abstract class KeySpinner extends TintSpinner implements LoaderManager.LoaderCallbacks<Cursor> { +public abstract class KeySpinner extends AppCompatSpinner implements LoaderManager.LoaderCallbacks<Cursor> {      public interface OnKeyChangedListener {          public void onKeyChanged(long masterKeyId);      } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java index 153bf2ff2..1a034537c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java @@ -17,17 +17,15 @@  package org.sufficientlysecure.keychain.ui.widget; -import android.annotation.TargetApi;  import android.content.Context; -import android.os.Build; +import android.support.v7.widget.AppCompatAutoCompleteTextView;  import android.util.AttributeSet;  import android.view.inputmethod.EditorInfo;  import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView;  import org.sufficientlysecure.keychain.util.ContactHelper; -public class NameEditText extends AutoCompleteTextView { +public class NameEditText extends AppCompatAutoCompleteTextView {      public NameEditText(Context context) {          super(context);          init(); @@ -43,12 +41,6 @@ public class NameEditText extends AutoCompleteTextView {          init();      } -    @TargetApi(Build.VERSION_CODES.LOLLIPOP) -    public NameEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { -        super(context, attrs, defStyleAttr, defStyleRes); -        init(); -    } -      private void init() {          reenableKeyboardSuggestions();          initAdapter(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PassphraseEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PassphraseEditText.java index 377f701d1..9364c5ee9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PassphraseEditText.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PassphraseEditText.java @@ -19,15 +19,13 @@ package org.sufficientlysecure.keychain.ui.widget;  import android.content.Context;  import android.graphics.Canvas; +import android.support.v7.widget.AppCompatEditText;  import android.text.Editable;  import android.text.TextWatcher;  import android.util.AttributeSet;  import android.util.TypedValue; -import android.widget.EditText; -import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthBarView; - -public class PassphraseEditText extends EditText { +public class PassphraseEditText extends AppCompatEditText {      PasswordStrengthBarView mPasswordStrengthBarView;      int mPasswordBarWidth; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthBarView.java index 9e06c4cce..e5886345f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthBarView.java @@ -22,13 +22,10 @@   * SOFTWARE.   */ -package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; +package org.sufficientlysecure.keychain.ui.widget;  import android.content.Context;  import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode;  import android.util.AttributeSet;  /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthView.java index bc5018497..1487c3053 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordStrengthView.java @@ -22,7 +22,7 @@   * SOFTWARE.   */ -package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; +package org.sufficientlysecure.keychain.ui.widget;  import android.content.Context;  import android.content.res.TypedArray; @@ -56,7 +56,6 @@ import org.sufficientlysecure.keychain.R;   */  public class PasswordStrengthView extends View { -      protected int mMinWidth;      protected int mMinHeight; | 
