Merge branch 'development' of https://github.com/open-keychain/open-keychain into development

This commit is contained in:
Daniel Ramos 2015-04-26 18:27:07 +01:00
commit 674f377bd4
43 changed files with 801 additions and 472 deletions

View File

@ -41,6 +41,8 @@ python copy OpenKeychain navigation grey chevron_left 24
python copy OpenKeychain navigation grey chevron_right 24 python copy OpenKeychain navigation grey chevron_right 24
python copy OpenKeychain social grey person 48 python copy OpenKeychain social grey person 48
python copy OpenKeychain communication grey email 24 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 # navigation drawer sections
python copy OpenKeychain communication black vpn_key 24 python copy OpenKeychain communication black vpn_key 24

View File

@ -6,10 +6,10 @@ dependencies {
// NOTE: libraries are pinned to a specific build, see below // NOTE: libraries are pinned to a specific build, see below
// from local Android SDK // from local Android SDK
compile 'com.android.support:support-v4:22.0.0' compile 'com.android.support:support-v4:22.1.1'
compile 'com.android.support:appcompat-v7:22.0.0' compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.android.support:recyclerview-v7:22.0.0' compile 'com.android.support:recyclerview-v7:22.1.0'
compile 'com.android.support:cardview-v7:22.0.0' compile 'com.android.support:cardview-v7:22.1.0'
// JCenter etc. // JCenter etc.
compile 'com.eftimoff:android-patternview:1.0.1@aar' 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.journeyapps:zxing-android-integration:2.3.0@aar'
compile 'com.google.zxing:core:3.2.0' compile 'com.google.zxing:core:3.2.0'
compile 'com.jpardogo.materialtabstrip:library:1.0.9' compile 'com.jpardogo.materialtabstrip:library:1.0.9'
compile 'it.neokree:MaterialNavigationDrawer:1.3.2'
compile 'com.getbase:floatingactionbutton:1.9.0' compile 'com.getbase:floatingactionbutton:1.9.0'
compile 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.0' compile 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.0'
compile "com.splitwise:tokenautocomplete:1.3.3@aar" compile "com.splitwise:tokenautocomplete:1.3.3@aar"
compile 'se.emilsjolander:stickylistheaders:2.6.0' compile 'se.emilsjolander:stickylistheaders:2.6.0'
compile 'org.sufficientlysecure:html-textview:1.1' 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 // libs as submodules
compile project(':extern:openpgp-api-lib') compile project(':extern:openpgp-api-lib')
@ -41,21 +45,25 @@ dependencies {
// Comment out the libs referenced as git submodules! // Comment out the libs referenced as git submodules!
dependencyVerification { dependencyVerification {
verify = [ verify = [
'com.android.support:support-v4:355a11466727e8ba00e239416aec55ac3cd3fb4ffc9d20c4a33373085c050bd1', 'com.android.support:support-v4:1e2e4d35ac7fd30db5ce3bc177b92e4d5af86acef2ef93e9221599d733346f56',
'com.android.support:appcompat-v7:40114cb756fecffa4a51c5645593cf64509c576594f77e41e801368051115c7b', 'com.android.support:appcompat-v7:9a2355537c2f01cf0b95523605c18606b8d824017e6e94a05c77b0cfc8f21c96',
'com.android.support:recyclerview-v7:859ed80e3761f8fc3126901260b208505120b5678bcf36ad2cfe9c453958b9c7', 'com.android.support:recyclerview-v7:522d323079a29bcd76173bd9bc7535223b4af3e5eefef9d9287df1f9e54d0c10',
'com.android.support:cardview-v7:4c03f2acce9925aa4f8845cb8cb37b3772c712b2438ff15f76c9e3d3bc63ead7', 'com.android.support:cardview-v7:8dc99af71fec000baa4470c3907755264f15f816920861bc015b2babdbb49807',
'com.eftimoff:android-patternview:cec80e7265b8d8278b3c55b5fcdf551e4600ac2c8bf60d8dd76adca538af0b1e', 'com.eftimoff:android-patternview:cec80e7265b8d8278b3c55b5fcdf551e4600ac2c8bf60d8dd76adca538af0b1e',
'com.journeyapps:zxing-android-embedded:702a4f58154dbd9baa80f66b6a15410f7a4d403f3e73b66537a8bfb156b4b718', 'com.journeyapps:zxing-android-embedded:702a4f58154dbd9baa80f66b6a15410f7a4d403f3e73b66537a8bfb156b4b718',
'com.journeyapps:zxing-android-integration:562737821b6d34c899b6fd2234ce0a8a31e02ff1fd7c59f6211961ce9767c7c8', 'com.journeyapps:zxing-android-integration:562737821b6d34c899b6fd2234ce0a8a31e02ff1fd7c59f6211961ce9767c7c8',
'com.google.zxing:core:7fe5a8ff437635a540e56317649937b768b454795ce999ed5f244f83373dee7b', 'com.google.zxing:core:7fe5a8ff437635a540e56317649937b768b454795ce999ed5f244f83373dee7b',
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa', 'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
'it.neokree:MaterialNavigationDrawer:a1221a410c5f71bf078c5c4768fdf06b402d6006c74f8e7b61199e4edc2aea57',
'com.getbase:floatingactionbutton:052aa2a94e49e5dccc97cb99f2add87e8698b84859f0e3ac181100c0bc7640ca', 'com.getbase:floatingactionbutton:052aa2a94e49e5dccc97cb99f2add87e8698b84859f0e3ac181100c0bc7640ca',
'org.commonjava.googlecode.markdown4j:markdown4j:e952e825d29e1317d96f79f346bfb6786c7c5eef50bd26e54a80823704b62e13', 'org.commonjava.googlecode.markdown4j:markdown4j:e952e825d29e1317d96f79f346bfb6786c7c5eef50bd26e54a80823704b62e13',
'com.splitwise:tokenautocomplete:20bee71cc59b3828eb000b684d46ddf738efd56b8fee453a509cd16fda42c8cb', 'com.splitwise:tokenautocomplete:20bee71cc59b3828eb000b684d46ddf738efd56b8fee453a509cd16fda42c8cb',
'se.emilsjolander:stickylistheaders:8c05981ec5725be33f7cee5e68c13f3db49cd5c75f1aaeb04024920b1ef96ad4', 'se.emilsjolander:stickylistheaders:8c05981ec5725be33f7cee5e68c13f3db49cd5c75f1aaeb04024920b1ef96ad4',
'org.sufficientlysecure:html-textview:ca24b1522be88378634093815ce9ff1b4920c72e7513a045a7846e14069ef988', '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:openpgp-api-lib:f05a9215cdad3a6597e4c5ece6fcec92b178d218195a3e88d2c0937c48dd9580',
// 'OpenKeychain.extern:openkeychain-api-lib:50f6ebb5452d3fdc7be137ccf857a0ff44d55539fcb7b91baef495766ed7f429', // 'OpenKeychain.extern:openkeychain-api-lib:50f6ebb5452d3fdc7be137ccf857a0ff44d55539fcb7b91baef495766ed7f429',
// 'com.madgag.spongycastle:core:df8fcc028a95ac5ffab3b78c9163f5cfa672e41cd50128ca55d458b6cfbacf4b', // 'com.madgag.spongycastle:core:df8fcc028a95ac5ffab3b78c9163f5cfa672e41cd50128ca55d458b6cfbacf4b',
@ -66,8 +74,7 @@ dependencyVerification {
// 'OpenKeychain.extern.KeybaseLib:Lib:c91cda4a75692d8664644cd17d8ac962ce5bc0e266ea26673a639805f1eccbdf', // 'OpenKeychain.extern.KeybaseLib:Lib:c91cda4a75692d8664644cd17d8ac962ce5bc0e266ea26673a639805f1eccbdf',
// 'OpenKeychain.extern:safeslinger-exchange:d222721bb35408daaab9f46449364b2657112705ee571d7532f81cbeb9c4a73f', // 'OpenKeychain.extern:safeslinger-exchange:d222721bb35408daaab9f46449364b2657112705ee571d7532f81cbeb9c4a73f',
// 'OpenKeychain.extern.snackbar:lib:52357426e5275412e2063bdf6f0e6b957a3ea74da45e0aef35d22d9afc542e23', // 'OpenKeychain.extern.snackbar:lib:52357426e5275412e2063bdf6f0e6b957a3ea74da45e0aef35d22d9afc542e23',
'com.android.support:support-annotations:ab6b131ab0e1edd165d21fb4c3edadeacbee9539aa166f7f7cbae05b60dc207a', 'com.android.support:support-annotations:7bc07519aa613b186001160403bcfd68260fa82c61cc7e83adeedc9b862b94ae',
'com.balysv:material-ripple:b2580520bcb5e5d77bd8c42b030317accaf8f88e7e57c46a29c47c8a62d4ff45',
] ]
} }

View File

@ -123,7 +123,6 @@ public class CreateKeyEmailFragment extends Fragment {
if (mAdditionalEmailModels == null) { if (mAdditionalEmailModels == null) {
mAdditionalEmailModels = new ArrayList<>(); mAdditionalEmailModels = new ArrayList<>();
} }
if (mEmailAdapter == null) { if (mEmailAdapter == null) {
mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() { mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() {
@Override @Override
@ -136,6 +135,9 @@ public class CreateKeyEmailFragment extends Fragment {
mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails);
} }
} }
if (mAdditionalEmailModels.isEmpty() && mCreateKeyActivity.mAdditionalEmails != null) {
mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails);
}
mEmailsRecyclerView.setAdapter(mEmailAdapter); mEmailsRecyclerView.setAdapter(mEmailAdapter);

View File

@ -21,7 +21,6 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.method.HideReturnsTransformationMethod; import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod; import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater; 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.ui.widget.PassphraseEditText;
import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.ArrayList;
import java.util.Arrays;
public class CreateKeyPassphraseFragment extends Fragment { public class CreateKeyPassphraseFragment extends Fragment {
// view // view
@ -111,8 +107,8 @@ public class CreateKeyPassphraseFragment extends Fragment {
// initial values // initial values
// TODO: using String here is unsafe... // TODO: using String here is unsafe...
if (mCreateKeyActivity.mPassphrase != null) { if (mCreateKeyActivity.mPassphrase != null) {
mPassphraseEdit.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); mPassphraseEdit.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray()));
mPassphraseEditAgain.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); mPassphraseEditAgain.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray()));
} }
mPassphraseEdit.requestFocus(); mPassphraseEdit.requestFocus();

View File

@ -240,7 +240,7 @@ public class DecryptFilesFragment extends DecryptFragment {
} }
case KeychainIntentService.ACTION_DECRYPT_VERIFY: { case KeychainIntentService.ACTION_DECRYPT_VERIFY: {
// display signature result in activity // display signature result in activity
onResult(pgpResult); loadVerifyResult(pgpResult);
if (mDeleteAfter.isChecked()) { if (mDeleteAfter.isChecked()) {
// Create and show dialog to delete original file // Create and show dialog to delete original file
@ -308,4 +308,8 @@ public class DecryptFilesFragment extends DecryptFragment {
} }
} }
@Override
protected void onVerifyLoaded(boolean verified) {
}
} }

View File

@ -17,26 +17,49 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle; 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.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; 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.KeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract; 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.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; 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<Cursor> {
public static final int LOADER_ID_UNIFIED = 0;
protected LinearLayout mResultLayout; protected LinearLayout mResultLayout;
@ -46,155 +69,119 @@ public abstract class DecryptFragment extends CryptoOperationFragment {
protected TextView mSignatureText; protected TextView mSignatureText;
protected View mSignatureLayout; protected View mSignatureLayout;
protected View mSignatureDivider1;
protected View mSignatureDivider2;
protected TextView mSignatureName; protected TextView mSignatureName;
protected TextView mSignatureEmail; protected TextView mSignatureEmail;
protected TextView mSignatureAction; protected TextView mSignatureAction;
@Override private OpenPgpSignatureResult mSignatureResult;
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
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); mResultLayout.setVisibility(View.GONE);
mEncryptionIcon = (ImageView) getView().findViewById(R.id.result_encryption_icon); mEncryptionIcon = (ImageView) getActivity().findViewById(R.id.result_encryption_icon);
mEncryptionText = (TextView) getView().findViewById(R.id.result_encryption_text); mEncryptionText = (TextView) getActivity().findViewById(R.id.result_encryption_text);
mSignatureIcon = (ImageView) getView().findViewById(R.id.result_signature_icon); mSignatureIcon = (ImageView) getActivity().findViewById(R.id.result_signature_icon);
mSignatureText = (TextView) getView().findViewById(R.id.result_signature_text); mSignatureText = (TextView) getActivity().findViewById(R.id.result_signature_text);
mSignatureLayout = getView().findViewById(R.id.result_signature_layout); mSignatureLayout = getActivity().findViewById(R.id.result_signature_layout);
mSignatureDivider1 = getView().findViewById(R.id.result_signature_divider1); mSignatureName = (TextView) getActivity().findViewById(R.id.result_signature_name);
mSignatureDivider2 = getView().findViewById(R.id.result_signature_divider2); mSignatureEmail = (TextView) getActivity().findViewById(R.id.result_signature_email);
mSignatureName = (TextView) getView().findViewById(R.id.result_signature_name); mSignatureAction = (TextView) getActivity().findViewById(R.id.result_signature_action);
mSignatureEmail = (TextView) getView().findViewById(R.id.result_signature_email);
mSignatureAction = (TextView) getView().findViewById(R.id.result_signature_action);
} }
private void lookupUnknownKey(long unknownKeyId) { private void lookupUnknownKey(long unknownKeyId) {
Intent intent = new Intent(getActivity(), ImportKeysActivity.class);
intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER); // Message is received after importing is done in KeychainIntentService
intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, unknownKeyId); ServiceProgressHandler serviceHandler = new ServiceProgressHandler(getActivity()) {
startActivityForResult(intent, RESULT_CODE_LOOKUP_KEY); 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<ParcelableKeyRing> 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) { private void showKey(long keyId) {
Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class); try {
viewKeyIntent.setData(KeychainContract.KeyRings
.buildGenericKeyRingUri(keyId)); Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class);
startActivity(viewKeyIntent); 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. * @return returns false if signature is invalid, key is revoked or expired.
*/ */
protected boolean onResult(DecryptVerifyResult decryptVerifyResult) { protected void loadVerifyResult(DecryptVerifyResult decryptVerifyResult) {
final OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
boolean valid = false; mSignatureResult = decryptVerifyResult.getSignatureResult();
mSignatureKeyId = 0;
mResultLayout.setVisibility(View.VISIBLE); mResultLayout.setVisibility(View.VISIBLE);
if (signatureResult != null) {
mSignatureKeyId = signatureResult.getKeyId();
String userId = signatureResult.getPrimaryUserId(); // unsigned data
KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); if (mSignatureResult == null) {
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 (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); setSignatureLayoutVisibility(View.GONE);
mSignatureText.setText(R.string.decrypt_result_no_signature); 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); mEncryptionText.setText(R.string.decrypt_result_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.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) { private void setSignatureLayoutVisibility(int visibility) {
mSignatureLayout.setVisibility(visibility); mSignatureLayout.setVisibility(visibility);
mSignatureDivider1.setVisibility(visibility);
mSignatureDivider2.setVisibility(visibility);
} }
private void setShowAction(final long signatureKeyId) { 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);
} }

View File

@ -23,6 +23,9 @@ import android.os.Bundle;
import android.os.Message; import android.os.Message;
import android.os.Messenger; import android.os.Messenger;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; 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.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ShareHelper; import org.sufficientlysecure.keychain.util.ShareHelper;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -54,6 +56,7 @@ public class DecryptTextFragment extends DecryptFragment {
// model // model
private String mCiphertext; private String mCiphertext;
private boolean mShowMenuOptions = false;
/** /**
* Creates new instance of this fragment * Creates new instance of this fragment
@ -79,22 +82,6 @@ public class DecryptTextFragment extends DecryptFragment {
mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid); mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid);
mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext); 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); Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button);
vInvalidButton.setOnClickListener(new View.OnClickListener() { vInvalidButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -110,9 +97,9 @@ public class DecryptTextFragment extends DecryptFragment {
/** /**
* Create Intent Chooser but exclude decrypt activites * Create Intent Chooser but exclude decrypt activites
*/ */
private Intent sendWithChooserExcludingEncrypt(String text) { private Intent sendWithChooserExcludingDecrypt(String text) {
Intent prototype = createSendIntent(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 ;) // we don't want to decrypt the decrypted, no inception ;)
String[] blacklist = new String[]{ String[] blacklist = new String[]{
@ -139,6 +126,8 @@ public class DecryptTextFragment extends DecryptFragment {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
String ciphertext = getArguments().getString(ARG_CIPHERTEXT); String ciphertext = getArguments().getString(ARG_CIPHERTEXT);
if (ciphertext != null) { if (ciphertext != null) {
mCiphertext = ciphertext; 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 @Override
protected void cryptoOperation(CryptoInputParcel cryptoInput) { protected void cryptoOperation(CryptoInputParcel cryptoInput) {
// Send all information needed to service to decrypt in other thread // Send all information needed to service to decrypt in other thread
@ -206,15 +222,8 @@ public class DecryptTextFragment extends DecryptFragment {
pgpResult.createNotify(getActivity()).show(); pgpResult.createNotify(getActivity()).show();
// display signature result in activity // 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 { } else {
pgpResult.createNotify(getActivity()).show(); pgpResult.createNotify(getActivity()).show();
// TODO: show also invalid layout with different text? // TODO: show also invalid layout with different text?
@ -234,4 +243,19 @@ public class DecryptTextFragment extends DecryptFragment {
getActivity().startService(intent); 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);
}
}
} }

View File

@ -98,23 +98,20 @@ public class EncryptTextActivity extends BaseActivity implements
// handle like normal text encryption, override action and extras to later // handle like normal text encryption, override action and extras to later
// executeServiceMethod ACTION_ENCRYPT_TEXT in main actions // executeServiceMethod ACTION_ENCRYPT_TEXT in main actions
extras.putString(EXTRA_TEXT, sharedText); extras.putString(EXTRA_TEXT, sharedText);
action = ACTION_ENCRYPT_TEXT;
} }
} }
} }
String textData = extras.getString(EXTRA_TEXT); String textData = extras.getString(EXTRA_TEXT);
if (ACTION_ENCRYPT_TEXT.equals(action) && textData == null) { if (textData == null) {
Log.e(Constants.TAG, "Include the extra 'text' in your Intent!"); textData = "";
return;
} }
// preselect keys given by intent // preselect keys given by intent
long mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID); long mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID);
long[] mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); long[] mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
if (savedInstanceState == null) { if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

View File

@ -1,6 +1,7 @@
/* /*
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com> * 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 * 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 * 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.content.Intent;
import android.os.Bundle; 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.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.remote.ui.AppsListFragment; import org.sufficientlysecure.keychain.remote.ui.AppsListFragment;
import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.FabContainer; 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 @Override
public void init(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
// don't open drawer on first run super.onCreate(savedInstanceState);
disableLearningPattern(); 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 mToolbar = (Toolbar) findViewById(R.id.toolbar);
// create and set the header mToolbar.setTitle(R.string.app_name);
setDrawerHeaderImage(R.drawable.drawer_header); setSupportActionBar(mToolbar);
// create sections result = new Drawer()
addSection(newSection(getString(R.string.nav_keys), R.drawable.ic_vpn_key_black_24dp, new KeyListFragment())); .withActivity(this)
addSection(newSection(getString(R.string.nav_encrypt_decrypt), R.drawable.ic_lock_black_24dp, new EncryptDecryptOverviewFragment())); .withHeader(R.layout.main_drawer_header)
addSection(newSection(getString(R.string.title_api_registered_apps), R.drawable.ic_apps_black_24dp, new AppsListFragment())); .withToolbar(mToolbar)
.addDrawerItems(
// create bottom section new PrimaryDrawerItem().withName(R.string.nav_keys).withIcon(CommunityMaterial.Icon.cmd_key).withIdentifier(1).withCheckable(false),
addBottomSection(newSection(getString(R.string.menu_preferences), R.drawable.ic_settings_black_24dp, new Intent(this, SettingsActivity.class))); new PrimaryDrawerItem().withName(R.string.nav_encrypt_decrypt).withIcon(FontAwesome.Icon.faw_lock).withIdentifier(2).withCheckable(false),
addBottomSection(newSection(getString(R.string.menu_help), R.drawable.ic_help_black_24dp, new Intent(this, HelpActivity.class))); 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 // if this is the first time show first time activity
Preferences prefs = Preferences.getPreferences(this); 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 @Override
public void fabMoveUp(int height) { public void fabMoveUp(int height) {
Object fragment = getCurrentSection().getTargetFragment(); Object fragment = getSupportFragmentManager()
.findFragmentById(R.id.main_fragment_container);
if (fragment instanceof FabContainer) { if (fragment instanceof FabContainer) {
((FabContainer) fragment).fabMoveUp(height); ((FabContainer) fragment).fabMoveUp(height);
} }
@ -79,7 +216,8 @@ public class MainActivity extends MaterialNavigationDrawer implements FabContain
@Override @Override
public void fabRestorePosition() { public void fabRestorePosition() {
Object fragment = getCurrentSection().getTargetFragment(); Object fragment = getSupportFragmentManager()
.findFragmentById(R.id.main_fragment_container);
if (fragment instanceof FabContainer) { if (fragment instanceof FabContainer) {
((FabContainer) fragment).fabRestorePosition(); ((FabContainer) fragment).fabRestorePosition();
} }

View File

@ -21,7 +21,7 @@ import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentPagerAdapter;
import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList; import java.util.ArrayList;
@ -41,7 +41,7 @@ public class PagerTabStripAdapter extends FragmentPagerAdapter {
} }
} }
public PagerTabStripAdapter(ActionBarActivity activity) { public PagerTabStripAdapter(AppCompatActivity activity) {
super(activity.getSupportFragmentManager()); super(activity.getSupportFragmentManager());
mActivity = activity; mActivity = activity;
} }

View File

@ -24,7 +24,7 @@ import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList; 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()); super(activity.getSupportFragmentManager());
mContext = activity; mContext = activity;
mActionBar = activity.getSupportActionBar(); mActionBar = activity.getSupportActionBar();

View File

@ -20,7 +20,7 @@ package org.sufficientlysecure.keychain.ui.base;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.ActionBar; 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.support.v7.widget.Toolbar;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -33,7 +33,7 @@ import org.sufficientlysecure.keychain.R;
/** /**
* Setups Toolbar * Setups Toolbar
*/ */
public abstract class BaseActivity extends ActionBarActivity { public abstract class BaseActivity extends AppCompatActivity {
protected Toolbar mToolbar; protected Toolbar mToolbar;
protected View mStatusBar; protected View mStatusBar;

View File

@ -17,9 +17,8 @@
package org.sufficientlysecure.keychain.ui.widget; package org.sufficientlysecure.keychain.ui.widget;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.support.v7.widget.AppCompatAutoCompleteTextView;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -27,14 +26,13 @@ import android.util.AttributeSet;
import android.util.Patterns; import android.util.Patterns;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.ContactHelper;
import java.util.regex.Matcher; import java.util.regex.Matcher;
public class EmailEditText extends AutoCompleteTextView { public class EmailEditText extends AppCompatAutoCompleteTextView {
public EmailEditText(Context context) { public EmailEditText(Context context) {
super(context); super(context);
@ -51,12 +49,6 @@ public class EmailEditText extends AutoCompleteTextView {
init(); 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() { private void init() {
setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
reenableKeyboardSuggestions(); reenableKeyboardSuggestions();

View File

@ -108,9 +108,8 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView
protected void onAttachedToWindow() { protected void onAttachedToWindow() {
super.onAttachedToWindow(); super.onAttachedToWindow();
mLoaderManager = ((FragmentActivity) getContext()).getSupportLoaderManager();
if (getContext() instanceof FragmentActivity) { if (getContext() instanceof FragmentActivity) {
mLoaderManager = ((FragmentActivity) getContext()).getSupportLoaderManager();
mLoaderManager.initLoader(hashCode(), null, this); mLoaderManager.initLoader(hashCode(), null, this);
} else { } else {
Log.e(Constants.TAG, "EncryptKeyCompletionView must be attached to a FragmentActivity, this is " + getContext().getClass()); Log.e(Constants.TAG, "EncryptKeyCompletionView must be attached to a FragmentActivity, this is " + getContext().getClass());

View File

@ -24,7 +24,7 @@ import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter; 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.text.format.DateFormat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
@ -46,10 +46,10 @@ import java.util.Date;
import java.util.TimeZone; 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 * 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 interface OnKeyChangedListener {
public void onKeyChanged(long masterKeyId); public void onKeyChanged(long masterKeyId);
} }

View File

@ -17,17 +17,15 @@
package org.sufficientlysecure.keychain.ui.widget; package org.sufficientlysecure.keychain.ui.widget;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.support.v7.widget.AppCompatAutoCompleteTextView;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.ContactHelper;
public class NameEditText extends AutoCompleteTextView { public class NameEditText extends AppCompatAutoCompleteTextView {
public NameEditText(Context context) { public NameEditText(Context context) {
super(context); super(context);
init(); init();
@ -43,12 +41,6 @@ public class NameEditText extends AutoCompleteTextView {
init(); 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() { private void init() {
reenableKeyboardSuggestions(); reenableKeyboardSuggestions();
initAdapter(); initAdapter();

View File

@ -19,15 +19,13 @@ package org.sufficientlysecure.keychain.ui.widget;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.TypedValue; import android.util.TypedValue;
import android.widget.EditText;
import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthBarView; public class PassphraseEditText extends AppCompatEditText {
public class PassphraseEditText extends EditText {
PasswordStrengthBarView mPasswordStrengthBarView; PasswordStrengthBarView mPasswordStrengthBarView;
int mPasswordBarWidth; int mPasswordBarWidth;

View File

@ -22,13 +22,10 @@
* SOFTWARE. * SOFTWARE.
*/ */
package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; package org.sufficientlysecure.keychain.ui.widget;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet; import android.util.AttributeSet;
/** /**

View File

@ -22,7 +22,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; package org.sufficientlysecure.keychain.ui.widget;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
@ -56,7 +56,6 @@ import org.sufficientlysecure.keychain.R;
*/ */
public class PasswordStrengthView extends View { public class PasswordStrengthView extends View {
protected int mMinWidth; protected int mMinWidth;
protected int mMinHeight; protected int mMinHeight;

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -9,8 +9,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/decrypt_result_include" />
<View <View
android:id="@+id/status_divider" android:id="@+id/status_divider"
android:layout_height="1dip" android:layout_height="1dip"

View File

@ -1,142 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/result_main_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/holo_gray_bright">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/result_encryption_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/status_lock_open_24dp"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/result_encryption_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Not Encrypted (set in-code)"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/result_signature_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/status_signature_unverified_cutout_24dp"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/result_signature_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Signed by (set in-code)"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" />
</LinearLayout>
<View
android:id="@+id/result_signature_divider1"
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_marginLeft="32dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:id="@+id/result_signature_layout"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:clickable="true"
android:layout_marginLeft="32dp"
android:paddingRight="4dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingRight="4dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/result_signature_name"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Alice (set in-code)" />
<TextView
android:id="@+id/result_signature_email"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="alice@example.com (set in-code)"
android:gravity="center_vertical" />
</LinearLayout>
<View
android:layout_width="1dip"
android:layout_height="match_parent"
android:gravity="right"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="?android:attr/listDivider" />
<TextView
android:id="@+id/result_signature_action"
android:paddingLeft="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Show"
android:drawableRight="@drawable/ic_vpn_key_grey_24dp"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:background="?android:selectableItemBackground" />
</LinearLayout>
<View
android:id="@+id/result_signature_divider2"
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_marginLeft="32dp"
android:background="?android:attr/listDivider" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider" />
</LinearLayout>

View File

@ -5,7 +5,7 @@
<include <include
android:id="@+id/toolbar_include" android:id="@+id/toolbar_include"
layout="@layout/toolbar_standalone_white" /> layout="@layout/toolbar_result_decrypt" />
<!-- <!--
fitsSystemWindows and layout_marginTop from fitsSystemWindows and layout_marginTop from

View File

@ -4,8 +4,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/decrypt_result_include" />
<LinearLayout <LinearLayout
android:visibility="gone" android:visibility="gone"
android:id="@+id/decrypt_text_valid" android:id="@+id/decrypt_text_valid"
@ -34,55 +32,6 @@
</ScrollView> </ScrollView>
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:id="@+id/action_decrypt_share_plaintext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:clickable="true"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<TextView
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:text="@string/btn_add_share_decrypted_text"
android:drawableRight="@drawable/ic_share_grey_24dp"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:layout_weight="1" />
<View
android:layout_width="1dip"
android:layout_height="match_parent"
android:gravity="right"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="?android:attr/listDivider" />
<ImageButton
android:id="@+id/action_decrypt_copy_plaintext"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="8dp"
android:src="@drawable/ic_content_copy_grey_24dp"
android:layout_gravity="center_vertical"
android:background="?android:selectableItemBackground" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout

View File

@ -11,6 +11,8 @@
android:id="@+id/recipient_list" android:id="@+id/recipient_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:minHeight="56dip" android:minHeight="56dip"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<LinearLayout <LinearLayout
@ -21,7 +23,7 @@
style="@android:style/Widget.EditText"> style="@android:style/Widget.EditText">
<TextView <TextView
android:paddingLeft="12dp" android:paddingLeft="8dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute" />
<FrameLayout
android:id="@+id/main_fragment_container"
android:layout_gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent" />
</LinearLayout>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/drawer_header"
android:adjustViewBounds="true"
android:scaleType="fitCenter">
</ImageView>

View File

@ -33,7 +33,7 @@
android:ems="10" android:ems="10"
android:layout_gravity="center_horizontal" /> android:layout_gravity="center_horizontal" />
<org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthBarView <org.sufficientlysecure.keychain.ui.widget.PasswordStrengthBarView
android:id="@+id/passphrase_repeat_passphrase_strength" android:id="@+id/passphrase_repeat_passphrase_strength"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="8dp" android:layout_height="8dp"

View File

@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/toolbar_include"
android:elevation="4dp"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="@+id/toolbar_inner_layout"
layout="@layout/toolbar_inner_layout_white" />
<LinearLayout
android:layout_below="@id/toolbar"
android:id="@+id/result_main_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:showIn="@layout/decrypt_text_fragment">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:animateLayoutChanges="true">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/result_encryption_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/status_lock_open_24dp"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/result_encryption_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
tools:text="Encryption status text" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/result_signature_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/status_signature_unverified_cutout_24dp"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/result_signature_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
tools:text="Signature status text" />
</LinearLayout>
<LinearLayout
android:id="@+id/result_signature_layout"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:clickable="true"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingRight="4dp"
android:paddingLeft="4dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/result_signature_name"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Alice" />
<TextView
android:id="@+id/result_signature_email"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
tools:text="alice@example.com" />
</LinearLayout>
<View
android:layout_width="1dip"
android:layout_height="match_parent"
android:gravity="right"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="?android:attr/listDivider" />
<TextView
android:id="@+id/result_signature_action"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Show"
android:drawableRight="@drawable/ic_vpn_key_grey_24dp"
android:drawablePadding="8dp"
android:gravity="center_vertical" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/decrypt_copy"
android:title="@string/btn_copy_decrypted_text"
android:icon="@drawable/ic_content_copy_black_24dp"
app:showAsAction="ifRoom" />
<item
android:id="@+id/decrypt_share"
android:title="@string/btn_share_decrypted_text"
android:icon="@drawable/ic_share_black_24dp"
app:showAsAction="ifRoom" />
</menu>

View File

@ -6,8 +6,12 @@
License: GPLv3+ License: GPLv3+
## Developers ## Main Developers
* Dominik Schürmann (Maintainer) * Dominik Schürmann (Maintainer)
* Vincent Breitmoser
## Contributors
* Adithya Abraham Philip
* Art O Cathain * Art O Cathain
* Ash Hughes * Ash Hughes
* Brian C. Barnes * Brian C. Barnes
@ -15,18 +19,33 @@ License: GPLv3+
* Daniel Albert * Daniel Albert
* Daniel Hammann * Daniel Hammann
* Daniel Haß * Daniel Haß
* Daniel Nelz
* Daniel Ramos
* Greg Witczak * Greg Witczak
* 'iseki'
* Ishan Khanna
* 'jellysheep'
* 'Jesperbk'
* 'jkolo'
* Joey Castillo
* Kai Jiang
* Kartik Arora
* 'Kent'
* 'ligi'
* Lukas Zorich
* Manoj Khanna
* 'mar-v-in' * 'mar-v-in'
* Markus Doits * Markus Doits
* Miroojin Bakshi * Miroojin Bakshi
* Morgan Gangwere
* Nikhil Peter Raj * Nikhil Peter Raj
* Paul Sarbinowski * Paul Sarbinowski
* 'Senecaso' * 'Senecaso'
* Signe Rüsch * Signe Rüsch
* Sreeram Boyapati * Sreeram Boyapati
* Thialfihar (APG 1.x) * 'steelman'
* 'Thialfihar' (APG developer)
* Tim Bray * Tim Bray
* Vincent Breitmoser
## Libraries ## Libraries
* [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License) * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
@ -39,8 +58,8 @@ License: GPLv3+
* [ZXing](https://github.com/zxing/zxing) (Apache License v2) * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
* [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design)</a> (Apache License v2) * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design)</a> (Apache License v2)
* [MaterialNavigationDrawer](https://github.com/neokree/MaterialNavigationDrawer) (Apache License v2) * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License) * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
* [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2) * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
* [HtmlTextView](https://github.com/dschuermann/html-textview) (Apache License v2) * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)

View File

@ -22,6 +22,7 @@
<color name="secondary_text">#727272</color> <color name="secondary_text">#727272</color>
<color name="icons">#FFFFFF</color> <color name="icons">#FFFFFF</color>
<color name="divider">#B6B6B6</color> <color name="divider">#B6B6B6</color>
<color name="transparent">#00FFFFFF</color>
<color name="header_text">#212121</color> <color name="header_text">#212121</color>
<!-- item selection, search highlight --> <!-- item selection, search highlight -->

View File

@ -78,7 +78,8 @@
<string name="btn_view_cert_key">"View certification key"</string> <string name="btn_view_cert_key">"View certification key"</string>
<string name="btn_create_key">"Create key"</string> <string name="btn_create_key">"Create key"</string>
<string name="btn_add_files">"Add file(s)"</string> <string name="btn_add_files">"Add file(s)"</string>
<string name="btn_add_share_decrypted_text">"Share decrypted text"</string> <string name="btn_share_decrypted_text">"Share decrypted text"</string>
<string name="btn_copy_decrypted_text">"Copy decrypted text"</string>
<string name="btn_decrypt_clipboard">"Decrypt text from clipboard"</string> <string name="btn_decrypt_clipboard">"Decrypt text from clipboard"</string>
<string name="btn_decrypt_and_verify">"and verify signatures"</string> <string name="btn_decrypt_and_verify">"and verify signatures"</string>
<string name="btn_decrypt_files">"Decrypt files"</string> <string name="btn_decrypt_files">"Decrypt files"</string>
@ -285,16 +286,16 @@
<!-- results shown after decryption/verification --> <!-- results shown after decryption/verification -->
<string name="decrypt_result_no_signature">"Not Signed"</string> <string name="decrypt_result_no_signature">"Not Signed"</string>
<string name="decrypt_result_invalid_signature">"Invalid signature!"</string> <string name="decrypt_result_invalid_signature">"Invalid signature!"</string>
<string name="decrypt_result_signature_uncertified">"Signed by (not certified!)"</string> <string name="decrypt_result_signature_uncertified">"Signed by <b>unconfirmed</b> key"</string>
<string name="decrypt_result_signature_certified">"Signed by"</string> <string name="decrypt_result_signature_certified">"Signed by confirmed key"</string>
<string name="decrypt_result_signature_expired_key">"Key is expired!"</string> <string name="decrypt_result_signature_expired_key">"Signed by <b>expired</b> key!"</string>
<string name="decrypt_result_signature_revoked_key">"Key has been revoked!"</string> <string name="decrypt_result_signature_revoked_key">"Signed by <b>revoked</b> key!"</string>
<string name="decrypt_result_signature_missing_key">"Unknown public key"</string> <string name="decrypt_result_signature_missing_key">"Signed by <b>unknown public key</b>"</string>
<string name="decrypt_result_encrypted">"Encrypted"</string> <string name="decrypt_result_encrypted">"Encrypted"</string>
<string name="decrypt_result_not_encrypted">"Not Encrypted"</string> <string name="decrypt_result_not_encrypted">"Not Encrypted"</string>
<string name="decrypt_result_action_show">"Show"</string> <string name="decrypt_result_action_show">"Show"</string>
<string name="decrypt_result_action_Lookup">"Lookup"</string> <string name="decrypt_result_action_Lookup">"Lookup"</string>
<string name="decrypt_invalid_text">"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?"</string> <string name="decrypt_invalid_text">"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?"</string>
<string name="decrypt_invalid_button">"I understand the risks, display it!"</string> <string name="decrypt_invalid_button">"I understand the risks, display it!"</string>
<!-- Add keys --> <!-- Add keys -->

View File

@ -8,26 +8,12 @@
<item name="colorPrimaryDark">@color/primary_dark</item> <item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item> <item name="colorAccent">@color/accent</item>
<item name="android:windowNoTitle">true</item> <!-- remove actionbar and title, we use toolbar! -->
<!-- remove actionbar, we use toolbar! --> <item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<!-- multi selection should overlay Toolbar! http://stackoverflow.com/a/26450875 --> <!-- multi selection should overlay Toolbar! http://stackoverflow.com/a/26450875 -->
<item name="windowActionModeOverlay">true</item> <item name="windowActionModeOverlay">true</item>
<item name="searchViewStyle">@style/MySearchViewStyle</item> <item name="searchViewStyle">@style/MySearchViewStyle</item>
<!-- Navigation Drawer library -->
<item name="drawerType">@integer/DRAWERTYPE_IMAGE</item>
<!-- dark action bar... -->
<item name="theme">@style/ThemeOverlay.AppCompat.Dark</item>
<!-- ...but light popup menu (white background) -->
<item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
<item name="drawerColor">#fafafa</item>
<item name="singleAccount">false</item>
<item name="sectionStyle">@style/MaterialSectionTheme.Light</item>
<item name="subheaderStyle">@style/MaterialSubheaderTheme.Light</item>
<item name="multipaneSupport">false</item>
<item name="rippleBackport">false</item>
<item name="uniqueToolbarColor">false</item>
</style> </style>
<!-- http://android-developers.blogspot.de/2014/10/appcompat-v21-material-design-for-pre.html --> <!-- http://android-developers.blogspot.de/2014/10/appcompat-v21-material-design-for-pre.html -->