diff --git a/Graphics/get-material-icons.sh b/Graphics/get-material-icons.sh index 299ae9713..11e0cda18 100755 --- a/Graphics/get-material-icons.sh +++ b/Graphics/get-material-icons.sh @@ -41,6 +41,8 @@ python copy OpenKeychain navigation grey chevron_left 24 python copy OpenKeychain navigation grey chevron_right 24 python copy OpenKeychain social grey person 48 python copy OpenKeychain communication grey email 24 +python copy OpenKeychain social black share 24 +python copy OpenKeychain content black content_copy 24 # navigation drawer sections python copy OpenKeychain communication black vpn_key 24 diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 0f9446713..6fe71540c 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -6,10 +6,10 @@ dependencies { // NOTE: libraries are pinned to a specific build, see below // from local Android SDK - compile 'com.android.support:support-v4:22.0.0' - compile 'com.android.support:appcompat-v7:22.0.0' - compile 'com.android.support:recyclerview-v7:22.0.0' - compile 'com.android.support:cardview-v7:22.0.0' + compile 'com.android.support:support-v4:22.1.1' + compile 'com.android.support:appcompat-v7:22.1.1' + compile 'com.android.support:recyclerview-v7:22.1.0' + compile 'com.android.support:cardview-v7:22.1.0' // JCenter etc. compile 'com.eftimoff:android-patternview:1.0.1@aar' @@ -17,12 +17,16 @@ dependencies { compile 'com.journeyapps:zxing-android-integration:2.3.0@aar' compile 'com.google.zxing:core:3.2.0' compile 'com.jpardogo.materialtabstrip:library:1.0.9' - compile 'it.neokree:MaterialNavigationDrawer:1.3.2' compile 'com.getbase:floatingactionbutton:1.9.0' compile 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.0' compile "com.splitwise:tokenautocomplete:1.3.3@aar" compile 'se.emilsjolander:stickylistheaders:2.6.0' compile 'org.sufficientlysecure:html-textview:1.1' + compile 'com.mikepenz.materialdrawer:library:2.8.2@aar' + compile 'com.mikepenz.iconics:library:0.9.1@aar' + compile 'com.mikepenz.iconics:octicons-typeface:2.2.0@aar' + compile 'com.mikepenz.iconics:meteocons-typeface:1.1.1@aar' + compile 'com.mikepenz.iconics:community-material-typeface:1.0.0@aar' // libs as submodules compile project(':extern:openpgp-api-lib') @@ -41,21 +45,25 @@ dependencies { // Comment out the libs referenced as git submodules! dependencyVerification { verify = [ - 'com.android.support:support-v4:355a11466727e8ba00e239416aec55ac3cd3fb4ffc9d20c4a33373085c050bd1', - 'com.android.support:appcompat-v7:40114cb756fecffa4a51c5645593cf64509c576594f77e41e801368051115c7b', - 'com.android.support:recyclerview-v7:859ed80e3761f8fc3126901260b208505120b5678bcf36ad2cfe9c453958b9c7', - 'com.android.support:cardview-v7:4c03f2acce9925aa4f8845cb8cb37b3772c712b2438ff15f76c9e3d3bc63ead7', + 'com.android.support:support-v4:1e2e4d35ac7fd30db5ce3bc177b92e4d5af86acef2ef93e9221599d733346f56', + 'com.android.support:appcompat-v7:9a2355537c2f01cf0b95523605c18606b8d824017e6e94a05c77b0cfc8f21c96', + 'com.android.support:recyclerview-v7:522d323079a29bcd76173bd9bc7535223b4af3e5eefef9d9287df1f9e54d0c10', + 'com.android.support:cardview-v7:8dc99af71fec000baa4470c3907755264f15f816920861bc015b2babdbb49807', 'com.eftimoff:android-patternview:cec80e7265b8d8278b3c55b5fcdf551e4600ac2c8bf60d8dd76adca538af0b1e', 'com.journeyapps:zxing-android-embedded:702a4f58154dbd9baa80f66b6a15410f7a4d403f3e73b66537a8bfb156b4b718', 'com.journeyapps:zxing-android-integration:562737821b6d34c899b6fd2234ce0a8a31e02ff1fd7c59f6211961ce9767c7c8', 'com.google.zxing:core:7fe5a8ff437635a540e56317649937b768b454795ce999ed5f244f83373dee7b', 'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa', - 'it.neokree:MaterialNavigationDrawer:a1221a410c5f71bf078c5c4768fdf06b402d6006c74f8e7b61199e4edc2aea57', 'com.getbase:floatingactionbutton:052aa2a94e49e5dccc97cb99f2add87e8698b84859f0e3ac181100c0bc7640ca', 'org.commonjava.googlecode.markdown4j:markdown4j:e952e825d29e1317d96f79f346bfb6786c7c5eef50bd26e54a80823704b62e13', 'com.splitwise:tokenautocomplete:20bee71cc59b3828eb000b684d46ddf738efd56b8fee453a509cd16fda42c8cb', 'se.emilsjolander:stickylistheaders:8c05981ec5725be33f7cee5e68c13f3db49cd5c75f1aaeb04024920b1ef96ad4', 'org.sufficientlysecure:html-textview:ca24b1522be88378634093815ce9ff1b4920c72e7513a045a7846e14069ef988', + 'com.mikepenz.materialdrawer:library:970317ed1a3cb96317f7b8d62ff592b3103eb46dfd68d9b244e7143623dc6d7a', + 'com.mikepenz.iconics:library:4698a36ee4c2af765d0a85779c61474d755b90d66a59020105b6760a8a909e9e', + 'com.mikepenz.iconics:octicons-typeface:67ed7d456a9ce5f5307b85f955797bfb3dd674e2f6defb31c6b8bbe2ede290be', + 'com.mikepenz.iconics:meteocons-typeface:39a8a9e70cd8287cdb119af57a672a41dd09240dba6697f5a0dbda1ccc33298b', + 'com.mikepenz.iconics:community-material-typeface:f1c5afee5f0f10d66beb3ed0df977246a02a9c46de4e05d7c0264bcde53b6b7f', // 'OpenKeychain.extern:openpgp-api-lib:f05a9215cdad3a6597e4c5ece6fcec92b178d218195a3e88d2c0937c48dd9580', // 'OpenKeychain.extern:openkeychain-api-lib:50f6ebb5452d3fdc7be137ccf857a0ff44d55539fcb7b91baef495766ed7f429', // 'com.madgag.spongycastle:core:df8fcc028a95ac5ffab3b78c9163f5cfa672e41cd50128ca55d458b6cfbacf4b', @@ -66,8 +74,7 @@ dependencyVerification { // 'OpenKeychain.extern.KeybaseLib:Lib:c91cda4a75692d8664644cd17d8ac962ce5bc0e266ea26673a639805f1eccbdf', // 'OpenKeychain.extern:safeslinger-exchange:d222721bb35408daaab9f46449364b2657112705ee571d7532f81cbeb9c4a73f', // 'OpenKeychain.extern.snackbar:lib:52357426e5275412e2063bdf6f0e6b957a3ea74da45e0aef35d22d9afc542e23', - 'com.android.support:support-annotations:ab6b131ab0e1edd165d21fb4c3edadeacbee9539aa166f7f7cbae05b60dc207a', - 'com.balysv:material-ripple:b2580520bcb5e5d77bd8c42b030317accaf8f88e7e57c46a29c47c8a62d4ff45', + 'com.android.support:support-annotations:7bc07519aa613b186001160403bcfd68260fa82c61cc7e83adeedc9b862b94ae', ] } 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; - protected long mSignatureKeyId = 0; +public abstract class DecryptFragment extends CryptoOperationFragment implements + LoaderManager.LoaderCallbacks { + + 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; - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); + private OpenPgpSignatureResult mSignatureResult; - mResultLayout = (LinearLayout) getView().findViewById(R.id.result_main_layout); + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + // 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); + + // 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); + + if (message.arg1 == MessageStatus.OKAY.ordinal()) { + // get returned data bundle + Bundle returnData = message.getData(); + + if (returnData == null) { + return; + } + + final ImportKeyResult result = + returnData.getParcelable(OperationResult.EXTRA_RESULT); + + // if (!result.success()) { + result.createNotify(getActivity()).show(); + // } + + getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, DecryptFragment.this); + + } + } + }; + + // fill values for this action + Bundle data = new Bundle(); + + // 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); + } + + { + ParcelableKeyRing keyEntry = new ParcelableKeyRing(null, + KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null); + ArrayList selectedEntries = new ArrayList<>(); + selectedEntries.add(keyEntry); + + data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries); + } + + // 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); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(serviceHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + getActivity().startService(intent); + } private void showKey(long keyId) { - Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class); - viewKeyIntent.setData(KeychainContract.KeyRings - .buildGenericKeyRingUri(keyId)); - startActivity(viewKeyIntent); + try { + + 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 boolean onResult(DecryptVerifyResult decryptVerifyResult) { - final OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); + protected void loadVerifyResult(DecryptVerifyResult decryptVerifyResult) { - boolean valid = false; - - mSignatureKeyId = 0; + mSignatureResult = decryptVerifyResult.getSignatureResult(); 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)); - } + // unsigned data + if (mSignatureResult == null) { - 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); - } - - switch (signatureResult.getStatus()) { - case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { - mSignatureText.setText(R.string.decrypt_result_signature_certified); - KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED); - - setSignatureLayoutVisibility(View.VISIBLE); - setShowAction(mSignatureKeyId); - - valid = true; - break; - } - - case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { - mSignatureText.setText(R.string.decrypt_result_signature_uncertified); - KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNVERIFIED); - - setSignatureLayoutVisibility(View.VISIBLE); - setShowAction(mSignatureKeyId); - - valid = true; - break; - } - - 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; - } - - case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: { - mSignatureText.setText(R.string.decrypt_result_signature_expired_key); - KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.EXPIRED); - - setSignatureLayoutVisibility(View.VISIBLE); - setShowAction(mSignatureKeyId); - - valid = false; - break; - } - - 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); - - valid = false; - break; - } - - case OpenPgpSignatureResult.SIGNATURE_ERROR: { - mSignatureText.setText(R.string.decrypt_result_invalid_signature); - KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID); - - setSignatureLayoutVisibility(View.GONE); - - 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; } - return valid; + 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); + } + + 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 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 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 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; @@ -146,6 +135,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 @@ -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 * Copyright (C) 2014 Vincent Breitmoser + * Copyright (C) 2015 Kai Jiang * * 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; + + private KeyListFragment mKeyListFragment ; + private AppsListFragment mAppsListFragment; + private EncryptDecryptOverviewFragment mEncryptDecryptOverviewFragment; + private Fragment mLastUsedFragment; + private Toolbar mToolbar; @Override - public void init(Bundle savedInstanceState) { - // don't open drawer on first run - disableLearningPattern(); + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main_activity); -// addMultiPaneSupport(); + //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(); - // set the header image - // create and set the header - setDrawerHeaderImage(R.drawable.drawer_header); + mToolbar = (Toolbar) findViewById(R.id.toolbar); + mToolbar.setTitle(R.string.app_name); + setSupportActionBar(mToolbar); - // 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())); - - // 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 { +public abstract class KeySpinner extends AppCompatSpinner implements LoaderManager.LoaderCallbacks { 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 similarity index 95% rename from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java rename to 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 similarity index 99% rename from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java rename to 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; diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_content_copy_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_content_copy_black_24dp.png new file mode 100644 index 000000000..dc8c85cce Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_content_copy_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_share_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_share_black_24dp.png new file mode 100644 index 000000000..2839b1352 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_share_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_content_copy_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_content_copy_black_24dp.png new file mode 100644 index 000000000..4ad9e552d Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_content_copy_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_share_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_share_black_24dp.png new file mode 100644 index 000000000..f0ff945b8 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_share_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_content_copy_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_content_copy_black_24dp.png new file mode 100644 index 000000000..c6f0e6b85 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_content_copy_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_share_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_share_black_24dp.png new file mode 100644 index 000000000..4b3675766 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_share_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_content_copy_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_content_copy_black_24dp.png new file mode 100644 index 000000000..081fbec5b Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_content_copy_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_share_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_share_black_24dp.png new file mode 100644 index 000000000..09d4df6af Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_share_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_content_copy_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_content_copy_black_24dp.png new file mode 100644 index 000000000..04c07fb56 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_content_copy_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_share_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_share_black_24dp.png new file mode 100644 index 000000000..0fe15fc05 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_share_black_24dp.png differ diff --git a/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml index 2ef411eaf..60673e475 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_file_fragment.xml @@ -9,8 +9,6 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml b/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml index a6099e25e..41d7c5c95 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_text_activity.xml @@ -5,7 +5,7 @@ + layout="@layout/toolbar_result_decrypt" /> diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 33fc362a1..f77570a88 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -78,7 +78,8 @@ "View certification key" "Create key" "Add file(s)" - "Share decrypted text" + "Share decrypted text" + "Copy decrypted text" "Decrypt text from clipboard" "and verify signatures" "Decrypt files" @@ -285,16 +286,16 @@ "Not Signed" "Invalid signature!" - "Signed by (not certified!)" - "Signed by" - "Key is expired!" - "Key has been revoked!" - "Unknown public key" + "Signed by unconfirmed key" + "Signed by confirmed key" + "Signed by expired key!" + "Signed by revoked key!" + "Signed by unknown public key" "Encrypted" "Not Encrypted" "Show" "Lookup" - "Either the signature is invalid or the key has been revoked/is expired. You cannot be sure who wrote the text. Do you still want to display it?" + "Either the signature is invalid or the key has been revoked. You cannot be sure who wrote the text. Do you still want to display it?" "I understand the risks, display it!" diff --git a/OpenKeychain/src/main/res/values/themes.xml b/OpenKeychain/src/main/res/values/themes.xml index c87895c01..6ac09c5d7 100644 --- a/OpenKeychain/src/main/res/values/themes.xml +++ b/OpenKeychain/src/main/res/values/themes.xml @@ -8,26 +8,12 @@ @color/primary_dark @color/accent - true - + + true false true @style/MySearchViewStyle - - - @integer/DRAWERTYPE_IMAGE - - @style/ThemeOverlay.AppCompat.Dark - - @style/ThemeOverlay.AppCompat.Light - #fafafa - false - @style/MaterialSectionTheme.Light - @style/MaterialSubheaderTheme.Light - false - false - false