aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-03-02 14:39:28 +0100
committerVincent Breitmoser <valodim@mugenguild.com>2015-03-02 14:39:28 +0100
commit2f83291920e024b0f8038fe0caa747051b41cf1c (patch)
tree780fc0975e56b3dbd8a1eb4cb2988ac3e2e23ea1 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui
parentaa22a0defcf94d5f734d3a00288f5c8d916d2e57 (diff)
parent4e29d027af05fc574dc5398d2fb3afcdf3defc70 (diff)
downloadopen-keychain-2f83291920e024b0f8038fe0caa747051b41cf1c.tar.gz
open-keychain-2f83291920e024b0f8038fe0caa747051b41cf1c.tar.bz2
open-keychain-2f83291920e024b0f8038fe0caa747051b41cf1c.zip
NON-WORKING Merge branch 'development' into linked-identities
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java OpenKeychain/src/main/res/layout/view_key_main_fragment.xml OpenKeychain/src/main/res/values/strings.xml extern/spongycastle
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java131
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java)55
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java198
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java88
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java125
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java306
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java36
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java38
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java150
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java69
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java73
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java29
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java229
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java)161
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java229
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java458
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java20
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java86
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java71
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java24
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java53
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java66
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java70
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java145
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java)56
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java)25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java716
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java257
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedFragment.java)72
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java)77
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java125
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java184
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java232
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java369
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java460
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java23
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AdvancedAppSettingsDialogFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/BadImportKeyDialogFragment.java)49
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java34
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java97
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java99
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java101
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java149
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/AspectRatioImageView.java138
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java39
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java104
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabLayout.java318
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabStrip.java211
90 files changed, 3995 insertions, 3255 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java
new file mode 100644
index 000000000..e6c2542a2
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.ActionBarActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.sufficientlysecure.keychain.R;
+
+/**
+ * Setups Toolbar
+ */
+public abstract class BaseActivity extends ActionBarActivity {
+ protected Toolbar mToolbar;
+ protected View mStatusBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ initLayout();
+ initToolbar();
+ }
+
+ protected abstract void initLayout();
+
+ protected void initToolbar() {
+ mToolbar = (Toolbar) findViewById(R.id.toolbar);
+ if (mToolbar != null) {
+ setSupportActionBar(mToolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+ mStatusBar = findViewById(R.id.status_bar);
+ }
+
+ protected void setActionBarIcon(int iconRes) {
+ mToolbar.setNavigationIcon(iconRes);
+ }
+
+ /**
+ * Inflate custom design to look like a full screen dialog, as specified in Material Design Guidelines
+ * see http://www.google.com/design/spec/components/dialogs.html#dialogs-full-screen-dialogs
+ */
+ protected void setFullScreenDialogDoneClose(int doneText, View.OnClickListener doneOnClickListener,
+ View.OnClickListener cancelOnClickListener) {
+ setActionBarIcon(R.drawable.ic_close_white_24dp);
+
+ // Inflate the custom action bar view
+ final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
+ .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
+ final View customActionBarView = inflater.inflate(R.layout.full_screen_dialog, null);
+
+ TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.full_screen_dialog_done_text));
+ firstTextView.setText(doneText);
+ customActionBarView.findViewById(R.id.full_screen_dialog_done).setOnClickListener(
+ doneOnClickListener);
+
+ getSupportActionBar().setDisplayShowCustomEnabled(true);
+ getSupportActionBar().setDisplayShowTitleEnabled(true);
+ getSupportActionBar().setCustomView(customActionBarView, new ActionBar.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT,
+ Gravity.END));
+ mToolbar.setNavigationOnClickListener(cancelOnClickListener);
+ }
+
+ /**
+ * Close button only
+ */
+ protected void setFullScreenDialogClose(View.OnClickListener cancelOnClickListener) {
+ setActionBarIcon(R.drawable.ic_close_white_24dp);
+ getSupportActionBar().setDisplayShowTitleEnabled(true);
+ mToolbar.setNavigationOnClickListener(cancelOnClickListener);
+ }
+
+ /**
+ * Inflate custom design with two buttons using drawables.
+ * This does not conform to the Material Design Guidelines, but we deviate here as this is used
+ * to indicate "Allow access"/"Disallow access" to the API, which must be clearly indicated
+ */
+ protected void setFullScreenDialogTwoButtons(int firstText, int firstDrawableId, View.OnClickListener firstOnClickListener,
+ int secondText, int secondDrawableId, View.OnClickListener secondOnClickListener) {
+
+ // Inflate the custom action bar view
+ final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
+ .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
+ final View customActionBarView = inflater.inflate(
+ R.layout.full_screen_dialog_2, null);
+
+ TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
+ firstTextView.setText(firstText);
+ firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
+ customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
+ firstOnClickListener);
+ TextView secondTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text));
+ secondTextView.setText(secondText);
+ secondTextView.setCompoundDrawablesWithIntrinsicBounds(secondDrawableId, 0, 0, 0);
+ customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
+ secondOnClickListener);
+
+ // Show the custom action bar view and hide the normal Home icon and title.
+ getSupportActionBar().setDisplayShowTitleEnabled(false);
+ getSupportActionBar().setDisplayShowHomeEnabled(false);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(false);
+ getSupportActionBar().setDisplayShowCustomEnabled(true);
+ getSupportActionBar().setCustomView(customActionBarView, new ActionBar.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
index f49f8e7cf..b7c80c1ed 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2013 Bahtiar 'kalkin' Gadimov
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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,55 +19,43 @@ package org.sufficientlysecure.keychain.ui;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
-import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.Log;
-public class ViewKeyAdvancedActivity extends ActionBarActivity {
+public class CertifyFingerprintActivity extends BaseActivity {
- ExportHelper mExportHelper;
- ProviderHelper mProviderHelper;
+ protected Uri mDataUri;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mExportHelper = new ExportHelper(this);
- mProviderHelper = new ProviderHelper(this);
-
- // Inflate a "Done" custom action bar
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // "Done"
- finish();
- }
- }
- );
-
- setContentView(R.layout.view_key_advanced_activity);
-
- Uri dataUri = getIntent().getData();
- if (dataUri == null) {
+ mDataUri = getIntent().getData();
+ if (mDataUri == null) {
Log.e(Constants.TAG, "Data missing. Should be uri of key!");
finish();
return;
}
- Log.i(Constants.TAG, "mDataUri: " + dataUri.toString());
+ setFullScreenDialogClose(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
- startFragment(savedInstanceState, dataUri);
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+
+ startFragment(savedInstanceState, mDataUri);
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.certify_fingerprint_activity);
+ }
private void startFragment(Bundle savedInstanceState, Uri dataUri) {
// However, if we're being restored from a previous state,
@@ -79,12 +66,12 @@ public class ViewKeyAdvancedActivity extends ActionBarActivity {
}
// Create an instance of the fragment
- ViewKeyAdvancedFragment frag = ViewKeyAdvancedFragment.newInstance(dataUri);
+ CertifyFingerprintFragment frag = CertifyFingerprintFragment.newInstance(dataUri);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
getSupportFragmentManager().beginTransaction()
- .replace(R.id.view_key_advanced_fragment, frag)
+ .replace(R.id.certify_fingerprint_fragment, frag)
.commitAllowingStateLoss();
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
new file mode 100644
index 000000000..a6b8a0e85
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Log;
+
+
+public class CertifyFingerprintFragment extends LoaderFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
+
+ static final int REQUEST_CERTIFY = 1;
+
+ public static final String ARG_DATA_URI = "uri";
+
+ private TextView mFingerprint;
+
+ private static final int LOADER_ID_UNIFIED = 0;
+
+ private Uri mDataUri;
+
+ private View mActionNo;
+ private View mActionYes;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static CertifyFingerprintFragment newInstance(Uri dataUri) {
+ CertifyFingerprintFragment frag = new CertifyFingerprintFragment();
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_DATA_URI, dataUri);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
+ View root = super.onCreateView(inflater, superContainer, savedInstanceState);
+ View view = inflater.inflate(R.layout.certify_fingerprint_fragment, getContainer());
+
+ mActionNo = view.findViewById(R.id.certify_fingerprint_button_no);
+ mActionYes = view.findViewById(R.id.certify_fingerprint_button_yes);
+
+ mFingerprint = (TextView) view.findViewById(R.id.certify_fingerprint_fingerprint);
+
+ mActionNo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getActivity().finish();
+ }
+ });
+ mActionYes.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ certify(mDataUri);
+ }
+ });
+
+ return root;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
+ if (dataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
+ getActivity().finish();
+ return;
+ }
+
+ loadData(dataUri);
+ }
+
+ private void loadData(Uri dataUri) {
+ mDataUri = dataUri;
+
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+
+ // Prepare the loaders. Either re-connect with an existing ones,
+ // or start new ones.
+ getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
+ }
+
+ static final String[] UNIFIED_PROJECTION = new String[]{
+ KeyRings._ID, KeyRings.FINGERPRINT,
+
+ };
+ static final int INDEX_UNIFIED_FINGERPRINT = 1;
+
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ setContentShown(false);
+ switch (id) {
+ case LOADER_ID_UNIFIED: {
+ Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
+ return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
+ }
+
+ default:
+ return null;
+ }
+ }
+
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ /* TODO better error handling? May cause problems when a key is deleted,
+ * because the notification triggers faster than the activity closes.
+ */
+ // Avoid NullPointerExceptions...
+ if (data.getCount() == 0) {
+ return;
+ }
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ switch (loader.getId()) {
+ case LOADER_ID_UNIFIED: {
+ if (data.moveToFirst()) {
+
+ byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
+ String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintBlob);
+ mFingerprint.setText(KeyFormattingUtils.colorizeFingerprint(fingerprint));
+
+ break;
+ }
+ }
+
+ }
+ setContentShown(true);
+ }
+
+ /**
+ * This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
+ * We need to make sure we are no longer using it.
+ */
+ public void onLoaderReset(Loader<Cursor> loader) {
+ }
+
+ private void certify(Uri dataUri) {
+ long keyId = 0;
+ try {
+ keyId = new ProviderHelper(getActivity())
+ .getCachedPublicKeyRing(dataUri)
+ .extractOrGetMasterKeyId();
+ } catch (PgpKeyNotFoundException e) {
+ Log.e(Constants.TAG, "key not found!", e);
+ }
+ Intent certifyIntent = new Intent(getActivity(), CertifyKeyActivity.class);
+ certifyIntent.putExtras(getActivity().getIntent());
+ certifyIntent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{keyId});
+ startActivityForResult(certifyIntent, REQUEST_CERTIFY);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // always just pass this one through
+ if (requestCode == REQUEST_CERTIFY) {
+ getActivity().setResult(resultCode, data);
+ getActivity().finish();
+ return;
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
index a97e73934..1fb88b182 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
@@ -18,24 +18,19 @@
package org.sufficientlysecure.keychain.ui;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-
import org.sufficientlysecure.keychain.R;
/**
* Signs the specified public key with the specified secret master key
*/
-public class CertifyKeyActivity extends ActionBarActivity {
+public class CertifyKeyActivity extends BaseActivity {
public static final String EXTRA_RESULT = "operation_result";
public static final String EXTRA_KEY_IDS = "extra_key_ids";
public static final String EXTRA_CERTIFY_KEY_ID = "certify_key_id";
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
+ protected void initLayout() {
setContentView(R.layout.certify_key_activity);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
index 841485c7c..e1467ec61 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -31,6 +31,7 @@ import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.os.Parcel;
+import android.os.Parcelable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
@@ -94,6 +95,7 @@ public class CertifyKeyFragment extends LoaderFragment
private static final int INDEX_IS_REVOKED = 4;
private MultiUserIdsAdapter mUserIdsAdapter;
+ private Messenger mPassthroughMessenger;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
@@ -109,6 +111,9 @@ public class CertifyKeyFragment extends LoaderFragment
return;
}
+ mPassthroughMessenger = getActivity().getIntent().getParcelableExtra(
+ KeychainIntentService.EXTRA_MESSENGER);
+
// preselect certify key id if given
long certifyKeyId = getActivity().getIntent().getLongExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, Constants.key.none);
if (certifyKeyId != Constants.key.none) {
@@ -234,7 +239,7 @@ public class CertifyKeyFragment extends LoaderFragment
long lastMasterKeyId = 0;
String lastName = "";
- ArrayList<String> uids = new ArrayList<String>();
+ ArrayList<String> uids = new ArrayList<>();
boolean header = true;
@@ -332,7 +337,6 @@ public class CertifyKeyFragment extends LoaderFragment
}
}
-
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
@@ -362,51 +366,63 @@ public class CertifyKeyFragment extends LoaderFragment
return;
}
+ Bundle data = new Bundle();
+ {
+ // fill values for this action
+ CertifyActionsParcel parcel = new CertifyActionsParcel(mSignMasterKeyId);
+ parcel.mCertifyActions.addAll(certifyActions);
+
+ data.putParcelable(KeychainIntentService.CERTIFY_PARCEL, parcel);
+ if (mUploadKeyCheckbox.isChecked()) {
+ String keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
+ data.putString(KeychainIntentService.UPLOAD_KEY_SERVER, keyserver);
+ }
+ }
+
// Send all information needed to service to sign key in other thread
Intent intent = new Intent(getActivity(), KeychainIntentService.class);
-
intent.setAction(KeychainIntentService.ACTION_CERTIFY_KEYRING);
-
- // fill values for this action
- CertifyActionsParcel parcel = new CertifyActionsParcel(mSignMasterKeyId);
- parcel.mCertifyActions.addAll(certifyActions);
-
- Bundle data = new Bundle();
- data.putParcelable(KeychainIntentService.CERTIFY_PARCEL, parcel);
- if (mUploadKeyCheckbox.isChecked()) {
- String keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
- data.putString(KeychainIntentService.UPLOAD_KEY_SERVER, keyserver);
- }
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
- // Message is received after signing is done in KeychainIntentService
- KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(),
- getString(R.string.progress_certifying), ProgressDialog.STYLE_SPINNER, true) {
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
- Bundle data = message.getData();
- CertifyResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
-
- Intent intent = new Intent();
- intent.putExtra(CertifyResult.EXTRA_RESULT, result);
- getActivity().setResult(Activity.RESULT_OK, intent);
- getActivity().finish();
+ if (mPassthroughMessenger != null) {
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, mPassthroughMessenger);
+ } else {
+
+ // Message is received after signing is done in KeychainIntentService
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(),
+ getString(R.string.progress_certifying), ProgressDialog.STYLE_SPINNER, true) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ Bundle data = message.getData();
+ CertifyResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
+
+ Intent intent = new Intent();
+ intent.putExtra(CertifyResult.EXTRA_RESULT, result);
+ getActivity().setResult(Activity.RESULT_OK, intent);
+ getActivity().finish();
+ }
}
- }
- };
+ };
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
- intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
- // show progress dialog
- saveHandler.showProgressDialog(getActivity());
+ // show progress dialog
+ saveHandler.showProgressDialog(getActivity());
+ }
// start service with intent
getActivity().startService(intent);
+
+ if (mPassthroughMessenger != null) {
+ getActivity().setResult(Activity.RESULT_OK);
+ getActivity().finish();
+ }
+
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java
index 0d8905c5b..f0ef8b9ef 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ConsolidateDialogActivity.java
@@ -61,7 +61,7 @@ public class ConsolidateDialogActivity extends FragmentActivity {
/* don't care about the results (for now?)
// get returned data bundle
- Bundle returnData = message.getData();
+ Bundle returnData = message.getInputData();
if (returnData == null) {
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
index 534ac5811..62c38d136 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -20,11 +20,10 @@ package org.sufficientlysecure.keychain.ui;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
-import android.support.v7.app.ActionBarActivity;
import org.sufficientlysecure.keychain.R;
-public class CreateKeyActivity extends ActionBarActivity {
+public class CreateKeyActivity extends BaseActivity {
public static final String EXTRA_NAME = "name";
public static final String EXTRA_EMAIL = "email";
@@ -37,8 +36,6 @@ public class CreateKeyActivity extends ActionBarActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.create_key_activity);
-
// pass extras into fragment
CreateKeyInputFragment frag =
CreateKeyInputFragment.newInstance(
@@ -48,6 +45,11 @@ public class CreateKeyActivity extends ActionBarActivity {
loadFragment(null, frag, FRAG_ACTION_START);
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.create_key_activity);
+ }
+
public void loadFragment(Bundle savedInstanceState, Fragment fragment, int action) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
index 2804a5ce6..6e0115342 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
@@ -35,17 +35,16 @@ import org.spongycastle.bcpg.sig.KeyFlags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
public class CreateKeyFinalFragment extends Fragment {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
index 6079062a7..8aa9fa6db 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
@@ -89,7 +89,7 @@ public class CreateKeyInputFragment extends Fragment {
mEmailEdit.setThreshold(1); // Start working from first character
mEmailEdit.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserEmails(getActivity())
)
@@ -124,7 +124,7 @@ public class CreateKeyInputFragment extends Fragment {
mNameEdit.setThreshold(1); // Start working from first character
mNameEdit.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserNames(getActivity())
)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
deleted file mode 100644
index 681e22e1e..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.os.Bundle;
-import android.view.View;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
-
-import java.util.regex.Matcher;
-
-public class DecryptActivity extends DrawerActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.decrypt_activity);
-
- activateDrawerNavigation(savedInstanceState);
-
- View actionFile = findViewById(R.id.decrypt_files);
- View actionFromClipboard = findViewById(R.id.decrypt_from_clipboard);
-
- actionFile.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent filesDecrypt = new Intent(DecryptActivity.this, DecryptFilesActivity.class);
- filesDecrypt.setAction(DecryptFilesActivity.ACTION_DECRYPT_DATA_OPEN);
- startActivity(filesDecrypt);
- }
- });
-
- actionFromClipboard.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent clipboardDecrypt = new Intent(DecryptActivity.this, DecryptTextActivity.class);
- clipboardDecrypt.setAction(DecryptTextActivity.ACTION_DECRYPT_FROM_CLIPBOARD);
- startActivityForResult(clipboardDecrypt, 0);
- }
- });
- }
-
- @TargetApi(VERSION_CODES.HONEYCOMB)
- @Override
- protected void onResume() {
- super.onResume();
-
- // This is an eye candy ice cream sandwich feature, nvm on versions below
- if (Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) {
-
- // get text from clipboard
- final CharSequence clipboardText =
- ClipboardReflection.getClipboardText(DecryptActivity.this);
-
- // if it's null, nothing to do here /o/
- if (clipboardText == null) {
- return;
- }
-
- new AsyncTask<String, Void, Boolean>() {
- @Override
- protected Boolean doInBackground(String... clipboardText) {
-
- // see if it looks like a pgp thing
- Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText[0]);
- boolean animate = matcher.matches();
-
- // see if it looks like another pgp thing
- if (!animate) {
- matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText[0]);
- animate = matcher.matches();
- }
- return animate;
- }
-
- @Override
- protected void onPostExecute(Boolean animate) {
- super.onPostExecute(animate);
-
- // if so, animate the clipboard icon just a bit~
- if (animate) {
- SubtleAttentionSeeker.tada(findViewById(R.id.clipboard_icon), 1.5f).start();
- }
- }
- }.execute(clipboardText.toString());
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // if a result has been returned, display a notify
- if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
- OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
- result.createNotify(this).show();
- } else {
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
index 9d972d8c0..89dd4970b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
@@ -20,14 +20,13 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
import org.sufficientlysecure.keychain.util.Log;
-public class DecryptFilesActivity extends ActionBarActivity {
+public class DecryptFilesActivity extends BaseActivity {
/* Intents */
public static final String ACTION_DECRYPT_DATA = OpenKeychainIntents.DECRYPT_DATA;
@@ -41,12 +40,15 @@ public class DecryptFilesActivity extends ActionBarActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.decrypt_files_activity);
-
// Handle intent actions
handleActions(savedInstanceState, getIntent());
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.decrypt_files_activity);
+ }
+
/**
* Handles all actions with this intent
*
@@ -86,7 +88,7 @@ public class DecryptFilesActivity extends ActionBarActivity {
loadFragment(savedInstanceState, null, true);
} else if (ACTION_DECRYPT_DATA.equals(action)) {
Log.e(Constants.TAG,
- "Include an Uri with setData() in your Intent!");
+ "Include an Uri with setInputData() in your Intent!");
}
}
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 691f1c240..5606523be 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
@@ -35,13 +35,13 @@ import android.widget.TextView;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
-import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.util.FileHelper;
+import org.sufficientlysecure.keychain.util.Log;
import java.io.File;
@@ -310,7 +310,7 @@ public class DecryptFilesFragment extends DecryptFragment {
// A future open after decryption feature
if () {
Intent viewFile = new Intent(Intent.ACTION_VIEW);
- viewFile.setData(mOutputUri);
+ viewFile.setInputData(mOutputUri);
startActivity(viewFile);
}
*/
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 7f06d36e8..8723c7255 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -27,9 +27,9 @@ import android.widget.TextView;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
public abstract class DecryptFragment extends Fragment {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
index 2da76088a..81a8a2ac4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
@@ -20,22 +20,21 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.SingletonResult;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.util.Log;
import java.util.regex.Matcher;
-public class DecryptTextActivity extends ActionBarActivity {
+public class DecryptTextActivity extends BaseActivity {
/* Intents */
public static final String ACTION_DECRYPT_TEXT = OpenKeychainIntents.DECRYPT_TEXT;
@@ -50,12 +49,15 @@ public class DecryptTextActivity extends ActionBarActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.decrypt_text_activity);
-
// Handle intent actions
handleActions(savedInstanceState, getIntent());
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.decrypt_text_activity);
+ }
+
/**
* Fixing broken PGP MESSAGE Strings coming from GMail/AOSP Mail
*/
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 fa7abf0f5..a15b23c06 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
@@ -34,13 +34,15 @@ import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
+import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ShareHelper;
+import java.io.UnsupportedEncodingException;
+
public class DecryptTextFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext";
@@ -111,7 +113,7 @@ public class DecryptTextFragment extends DecryptFragment {
Intent prototype = createSendIntent(text);
String title = getString(R.string.title_share_file);
- // we don't want to decrypt the decypted, no inception ;)
+ // we don't want to decrypt the decrypted, no inception ;)
String[] blacklist = new String[]{
Constants.PACKAGE_NAME + ".ui.DecryptTextActivity",
"org.thialfihar.android.apg.ui.DecryptActivity"
@@ -194,7 +196,18 @@ public class DecryptTextFragment extends DecryptFragment {
byte[] decryptedMessage = returnData
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
- mText.setText(new String(decryptedMessage));
+ String displayMessage;
+ if (pgpResult.getCharset() != null) {
+ try {
+ displayMessage = new String(decryptedMessage, pgpResult.getCharset());
+ } catch (UnsupportedEncodingException e) {
+ // if we can't decode properly, just fall back to utf-8
+ displayMessage = new String(decryptedMessage);
+ }
+ } else {
+ displayMessage = new String(decryptedMessage);
+ }
+ mText.setText(displayMessage);
pgpResult.createNotify(getActivity()).show();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java
deleted file mode 100644
index da46de486..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DrawerActivity.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.view.GravityCompat;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v4.widget.FixedDrawerLayout;
-import android.support.v7.app.ActionBarActivity;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-
-public class DrawerActivity extends ActionBarActivity {
- private FixedDrawerLayout mDrawerLayout;
- private ListView mDrawerList;
- private ActionBarDrawerToggle mDrawerToggle;
-
- private CharSequence mDrawerTitle;
- private CharSequence mTitle;
- private boolean mIsDrawerLocked = false;
-
- private Class mSelectedItem;
-
- private static final int MENU_ID_PREFERENCE = 222;
- private static final int MENU_ID_HELP = 223;
-
- protected void deactivateDrawerNavigation() {
- ((DrawerLayout) findViewById(R.id.drawer_layout)).setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
- }
-
- protected void activateDrawerNavigation(Bundle savedInstanceState) {
- mDrawerTitle = getString(R.string.app_name);
- mDrawerLayout = (FixedDrawerLayout) findViewById(R.id.drawer_layout);
- mDrawerList = (ListView) findViewById(R.id.left_drawer);
- ViewGroup viewGroup = (ViewGroup) findViewById(R.id.content_frame);
- int leftMarginLoaded = ((ViewGroup.MarginLayoutParams) viewGroup.getLayoutParams()).leftMargin;
- int leftMarginInTablets = (int) getResources().getDimension(R.dimen.drawer_size);
- int errorInMarginAllowed = 5;
-
- // if the left margin of the loaded layout is close to the
- // one used in tablets then set drawer as open and locked
- if (Math.abs(leftMarginLoaded - leftMarginInTablets) < errorInMarginAllowed) {
- mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, mDrawerList);
- mDrawerLayout.setScrimColor(Color.TRANSPARENT);
- mIsDrawerLocked = true;
- } else {
- // set a custom shadow that overlays the main content when the drawer opens
- mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
- mIsDrawerLocked = false;
- }
-
- NavItem mItemIconTexts[] = new NavItem[]{
- new NavItem(R.drawable.ic_action_accounts, getString(R.string.nav_keys)),
- new NavItem(R.drawable.ic_action_secure, getString(R.string.nav_encrypt_text)),
- new NavItem(R.drawable.ic_action_secure, getString(R.string.nav_encrypt_files)),
- new NavItem(R.drawable.ic_action_not_secure, getString(R.string.nav_decrypt)),
- new NavItem(R.drawable.ic_action_view_as_list, getString(R.string.nav_apps))};
-
- mDrawerList.setAdapter(new NavigationDrawerAdapter(this, R.layout.drawer_list_item,
- mItemIconTexts));
-
- mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
-
- // enable ActionBar app icon to behave as action to toggle nav drawer
- // if the drawer is not locked
- if (!mIsDrawerLocked) {
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setHomeButtonEnabled(true);
- }
-
- // ActionBarDrawerToggle ties together the the proper interactions
- // between the sliding drawer and the action bar app icon
- mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
- mDrawerLayout, /* DrawerLayout object */
- R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
- R.string.drawer_open, /* "open drawer" description for accessibility */
- R.string.drawer_close /* "close drawer" description for accessibility */
- ) {
- public void onDrawerClosed(View view) {
- getSupportActionBar().setTitle(mTitle);
-
- callIntentForDrawerItem(mSelectedItem);
- }
-
- public void onDrawerOpened(View drawerView) {
- mTitle = getSupportActionBar().getTitle();
- getSupportActionBar().setTitle(mDrawerTitle);
- // creates call to onPrepareOptionsMenu()
- supportInvalidateOptionsMenu();
- }
- };
-
- if (!mIsDrawerLocked) {
- mDrawerLayout.setDrawerListener(mDrawerToggle);
- } else {
- // If the drawer is locked open make it un-focusable
- // so that it doesn't consume all the Back button presses
- mDrawerLayout.setFocusableInTouchMode(false);
- }
- }
-
- /**
- * Uses startActivity to call the Intent of the given class
- *
- * @param drawerItem the class of the drawer item you want to load. Based on Constants.DrawerItems.*
- */
- public void callIntentForDrawerItem(Class drawerItem) {
- // creates call to onPrepareOptionsMenu()
- supportInvalidateOptionsMenu();
-
- // call intent activity if selected
- if (drawerItem != null) {
- finish();
- overridePendingTransition(0, 0);
-
- Intent intent = new Intent(this, drawerItem);
- startActivity(intent);
-
- // disable animation of activity start
- overridePendingTransition(0, 0);
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- if (mDrawerToggle == null) {
- return super.onCreateOptionsMenu(menu);
- }
-
- menu.add(42, MENU_ID_PREFERENCE, 100, R.string.menu_preferences);
- menu.add(42, MENU_ID_HELP, 101, R.string.menu_help);
-
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (mDrawerToggle == null) {
- return super.onOptionsItemSelected(item);
- }
-
- // The action bar home/up action should open or close the drawer.
- // ActionBarDrawerToggle will take care of this.
- if (mDrawerToggle.onOptionsItemSelected(item)) {
- return true;
- }
-
- switch (item.getItemId()) {
- case MENU_ID_PREFERENCE: {
- Intent intent = new Intent(this, PreferencesActivity.class);
- startActivity(intent);
- return true;
- }
- case MENU_ID_HELP: {
- Intent intent = new Intent(this, HelpActivity.class);
- startActivity(intent);
- return true;
- }
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- /**
- * The click listener for ListView in the navigation drawer
- */
- private class DrawerItemClickListener implements ListView.OnItemClickListener {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- selectItem(position);
- }
- }
-
- private void selectItem(int position) {
- // update selected item and title, then close the drawer
- mDrawerList.setItemChecked(position, true);
- // set selected class
- mSelectedItem = Constants.DrawerItems.ARRAY[position];
-
- // setTitle(mDrawerTitles[position]);
- // If drawer isn't locked just close the drawer and
- // it will move to the selected item by itself (via drawer toggle listener)
- if (!mIsDrawerLocked) {
- mDrawerLayout.closeDrawer(mDrawerList);
- // else move to the selected item yourself
- } else {
- callIntentForDrawerItem(mSelectedItem);
- }
- }
-
- /**
- * When using the ActionBarDrawerToggle, you must call it during onPostCreate() and
- * onConfigurationChanged()...
- */
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- // Sync the toggle state after onRestoreInstanceState has occurred.
- if (mDrawerToggle != null) {
- mDrawerToggle.syncState();
- }
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- // Pass any configuration change to the drawer toggles
- if (mDrawerToggle != null) {
- mDrawerToggle.onConfigurationChanged(newConfig);
- }
- }
-
- private class NavItem {
- public int icon; // res-id
- public String title;
-
- /**
- * NavItem constructor
- *
- * @param icon The icons resource-id
- * @param title The title of the menu entry
- */
- public NavItem(int icon, String title) {
- super();
- this.icon = icon;
- this.title = title;
- }
- }
-
- private class NavigationDrawerAdapter extends ArrayAdapter<NavItem> {
- Context mContext;
- int mLayoutResourceId;
- NavItem mData[] = null;
-
- public NavigationDrawerAdapter(Context context, int layoutResourceId, NavItem[] data) {
- super(context, layoutResourceId, data);
- this.mLayoutResourceId = layoutResourceId;
- this.mContext = context;
- this.mData = data;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View row = convertView;
- NavItemHolder holder;
-
- if (row == null) {
- LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
- row = inflater.inflate(mLayoutResourceId, parent, false);
-
- holder = new NavItemHolder();
- holder.mImg = (ImageView) row.findViewById(R.id.drawer_item_icon);
- holder.mTxtTitle = (TextView) row.findViewById(R.id.drawer_item_text);
-
- row.setTag(holder);
- } else {
- holder = (NavItemHolder) row.getTag();
- }
-
- NavItem item = mData[position];
- holder.mTxtTitle.setText(item.title);
- holder.mImg.setImageResource(item.icon);
-
- return row;
- }
-
- }
-
- static class NavItemHolder {
- ImageView mImg;
- TextView mTxtTitle;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 98049d89b..6dc2994cf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -19,14 +19,13 @@ package org.sufficientlysecure.keychain.ui;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.util.Log;
-public class EditKeyActivity extends ActionBarActivity {
+public class EditKeyActivity extends BaseActivity {
public static final String EXTRA_SAVE_KEYRING_PARCEL = "save_keyring_parcel";
@@ -36,8 +35,6 @@ public class EditKeyActivity extends ActionBarActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.edit_key_activity);
-
Uri dataUri = getIntent().getData();
SaveKeyringParcel saveKeyringParcel = getIntent().getParcelableExtra(EXTRA_SAVE_KEYRING_PARCEL);
if (dataUri == null && saveKeyringParcel == null) {
@@ -49,6 +46,11 @@ public class EditKeyActivity extends ActionBarActivity {
loadFragment(savedInstanceState, dataUri, saveKeyringParcel);
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.edit_key_activity);
+ }
+
private void loadFragment(Bundle savedInstanceState, Uri dataUri, SaveKeyringParcel saveKeyringParcel) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
index afe6afb3c..25ca6e8fd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -29,7 +29,6 @@ import android.os.Messenger;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
-import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -55,6 +54,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
@@ -65,7 +65,6 @@ import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -147,10 +146,8 @@ public class EditKeyFragment extends LoaderFragment implements
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
-
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(((ActionBarActivity) getActivity()).getSupportActionBar(),
- R.string.btn_save, R.drawable.ic_action_save,
+ ((EditKeyActivity) getActivity()).setFullScreenDialogDoneClose(
+ R.string.btn_save,
new OnClickListener() {
@Override
public void onClick(View v) {
@@ -161,16 +158,13 @@ public class EditKeyFragment extends LoaderFragment implements
saveInDatabase(mCurrentPassphrase);
}
}
- }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel,
- new OnClickListener() {
+ }, new OnClickListener() {
@Override
public void onClick(View v) {
- // cancel
getActivity().setResult(Activity.RESULT_CANCELED);
getActivity().finish();
}
- }
- );
+ });
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
SaveKeyringParcel saveKeyringParcel = getArguments().getParcelable(ARG_SAVE_KEYRING_PARCEL);
@@ -230,10 +224,7 @@ public class EditKeyFragment extends LoaderFragment implements
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
- } catch (PgpKeyNotFoundException e) {
- finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND);
- return;
- } catch (NotFoundException e) {
+ } catch (PgpKeyNotFoundException | NotFoundException e) {
finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND);
return;
}
@@ -395,8 +386,8 @@ public class EditKeyFragment extends LoaderFragment implements
// cache new returned passphrase!
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
- data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
- null
+ data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
+ null
);
}
}
@@ -478,12 +469,13 @@ public class EditKeyFragment extends LoaderFragment implements
}
break;
case EditSubkeyDialogFragment.MESSAGE_STRIP:
- // toggle
- if (mSaveKeyringParcel.mStripSubKeys.contains(keyId)) {
- mSaveKeyringParcel.mStripSubKeys.remove(keyId);
- } else {
- mSaveKeyringParcel.mStripSubKeys.add(keyId);
+ SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId);
+ if (change == null) {
+ mSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null));
+ break;
}
+ // toggle
+ change.mDummyStrip = !change.mDummyStrip;
break;
}
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index b9058a37d..0d7e6056e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -8,13 +8,15 @@ import android.os.Messenger;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
+import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
+import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import java.util.Date;
-public abstract class EncryptActivity extends DrawerActivity {
+public abstract class EncryptActivity extends BaseActivity {
public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
public static final int REQUEST_CODE_NFC = 0x00008002;
@@ -82,7 +84,10 @@ public abstract class EncryptActivity extends DrawerActivity {
// Send all information needed to service to edit key in other thread
Intent intent = new Intent(this, KeychainIntentService.class);
intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT);
- intent.putExtra(KeychainIntentService.EXTRA_DATA, createEncryptBundle());
+
+ Bundle data = new Bundle();
+ data.putParcelable(KeychainIntentService.SIGN_ENCRYPT_PARCEL, createEncryptBundle());
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Message is received after encrypting is done in KeychainIntentService
KeychainIntentServiceHandler serviceHandler = new KeychainIntentServiceHandler(this,
@@ -92,28 +97,31 @@ public abstract class EncryptActivity extends DrawerActivity {
super.handleMessage(message);
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
- SignEncryptResult pgpResult =
+ SignEncryptResult result =
message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT);
- if (pgpResult.isPending()) {
- if ((pgpResult.getResult() & SignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
- SignEncryptResult.RESULT_PENDING_PASSPHRASE) {
+ PgpSignEncryptResult pgpResult = result.getPending();
+
+ if (pgpResult != null && pgpResult.isPending()) {
+ if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
+ PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) {
startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & SignEncryptResult.RESULT_PENDING_NFC) ==
- SignEncryptResult.RESULT_PENDING_NFC) {
+ } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) ==
+ PgpSignEncryptResult.RESULT_PENDING_NFC) {
mNfcTimestamp = pgpResult.getNfcTimestamp();
- startNfcSign(pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo());
+ startNfcSign(pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(),
+ pgpResult.getNfcHash(), pgpResult.getNfcAlgo());
} else {
throw new RuntimeException("Unhandled pending result!");
}
return;
}
- if (pgpResult.success()) {
- onEncryptSuccess(message, pgpResult);
+ if (result.success()) {
+ onEncryptSuccess(result);
} else {
- pgpResult.createNotify(EncryptActivity.this).show();
+ result.createNotify(EncryptActivity.this).show();
}
// no matter the result, reset parameters
@@ -136,8 +144,8 @@ public abstract class EncryptActivity extends DrawerActivity {
protected abstract boolean inputIsValid();
- protected abstract void onEncryptSuccess(Message message, SignEncryptResult result);
+ protected abstract void onEncryptSuccess(SignEncryptResult result);
- protected abstract Bundle createEncryptBundle();
+ protected abstract SignEncryptParcel createEncryptBundle();
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
index 2d1b66daa..c5404094a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
@@ -28,7 +28,6 @@ import com.tokenautocomplete.TokenCompleteTextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
@@ -164,8 +163,8 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi
private void updateEncryptionKeys() {
List<Object> objects = mEncryptKeyView.getObjects();
- List<Long> keyIds = new ArrayList<Long>();
- List<String> userIds = new ArrayList<String>();
+ List<Long> keyIds = new ArrayList<>();
+ List<String> userIds = new ArrayList<>();
for (Object object : objects) {
if (object instanceof EncryptKeyCompletionView.EncryptionKey) {
keyIds.add(((EncryptKeyCompletionView.EncryptionKey) object).getKeyId());
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
new file mode 100644
index 000000000..a498d0763
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
+
+import java.util.regex.Matcher;
+
+public class EncryptDecryptOverviewFragment extends Fragment {
+
+ View mEncryptFile;
+ View mEncryptText;
+ View mDecryptFile;
+ View mDecryptFromClipboard;
+ View mClipboardIcon;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.encrypt_decrypt_overview_fragment, container, false);
+
+ mEncryptFile = view.findViewById(R.id.encrypt_files);
+ mEncryptText = view.findViewById(R.id.encrypt_text);
+ mDecryptFile = view.findViewById(R.id.decrypt_files);
+ mDecryptFromClipboard = view.findViewById(R.id.decrypt_from_clipboard);
+ mClipboardIcon = view.findViewById(R.id.clipboard_icon);
+
+ mEncryptFile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent encrypt = new Intent(getActivity(), EncryptFilesActivity.class);
+ startActivity(encrypt);
+ }
+ });
+
+ mEncryptText.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent encrypt = new Intent(getActivity(), EncryptTextActivity.class);
+ startActivity(encrypt);
+ }
+ });
+
+ mDecryptFile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent filesDecrypt = new Intent(getActivity(), DecryptFilesActivity.class);
+ filesDecrypt.setAction(DecryptFilesActivity.ACTION_DECRYPT_DATA_OPEN);
+ startActivity(filesDecrypt);
+ }
+ });
+
+ mDecryptFromClipboard.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent clipboardDecrypt = new Intent(getActivity(), DecryptTextActivity.class);
+ clipboardDecrypt.setAction(DecryptTextActivity.ACTION_DECRYPT_FROM_CLIPBOARD);
+ startActivityForResult(clipboardDecrypt, 0);
+ }
+ });
+
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ // get text from clipboard
+ final CharSequence clipboardText =
+ ClipboardReflection.getClipboardText(getActivity());
+
+ // if it's null, nothing to do here /o/
+ if (clipboardText == null) {
+ return;
+ }
+
+ new AsyncTask<String, Void, Boolean>() {
+ @Override
+ protected Boolean doInBackground(String... clipboardText) {
+
+ // see if it looks like a pgp thing
+ Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText[0]);
+ boolean animate = matcher.matches();
+
+ // see if it looks like another pgp thing
+ if (!animate) {
+ matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText[0]);
+ animate = matcher.matches();
+ }
+ return animate;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean animate) {
+ super.onPostExecute(animate);
+
+ // if so, animate the clipboard icon just a bit~
+ if (animate) {
+ SubtleAttentionSeeker.tada(mClipboardIcon, 1.5f).start();
+ }
+ }
+ }.execute(clipboardText.toString());
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // if a result has been returned, display a notify
+ if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
+ OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
+ result.createNotify(getActivity()).show();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
index 054d85323..1286617d3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
@@ -21,7 +21,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuItem;
@@ -29,14 +28,14 @@ import android.view.MenuItem;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
-import org.sufficientlysecure.keychain.util.Preferences;
-import org.sufficientlysecure.keychain.util.ShareHelper;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
-import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.ShareHelper;
import java.util.ArrayList;
import java.util.HashSet;
@@ -122,13 +121,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
@Override
public ArrayList<Uri> getInputUris() {
- if (mInputUris == null) mInputUris = new ArrayList<Uri>();
+ if (mInputUris == null) mInputUris = new ArrayList<>();
return mInputUris;
}
@Override
public ArrayList<Uri> getOutputUris() {
- if (mOutputUris == null) mOutputUris = new ArrayList<Uri>();
+ if (mOutputUris == null) mOutputUris = new ArrayList<>();
return mOutputUris;
}
@@ -170,7 +169,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
}
@Override
- public void onEncryptSuccess(Message message, SignEncryptResult pgpResult) {
+ public void onEncryptSuccess(SignEncryptResult result) {
if (mDeleteAfterEncrypt) {
for (Uri inputUri : mInputUris) {
DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(inputUri);
@@ -182,29 +181,25 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
if (mShareAfterEncrypt) {
// Share encrypted message/file
- startActivity(sendWithChooserExcludingEncrypt(message));
+ startActivity(sendWithChooserExcludingEncrypt());
} else {
// Save encrypted file
- pgpResult.createNotify(EncryptFilesActivity.this).show();
+ result.createNotify(EncryptFilesActivity.this).show();
}
}
@Override
- protected Bundle createEncryptBundle() {
+ protected SignEncryptParcel createEncryptBundle() {
// fill values for this action
- Bundle data = new Bundle();
+ SignEncryptParcel data = new SignEncryptParcel();
- data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URIS);
- data.putParcelableArrayList(KeychainIntentService.ENCRYPT_INPUT_URIS, mInputUris);
+ data.addInputUris(mInputUris);
+ data.addOutputUris(mOutputUris);
- data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URIS);
- data.putParcelableArrayList(KeychainIntentService.ENCRYPT_OUTPUT_URIS, mOutputUris);
-
- data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID,
- Preferences.getPreferences(this).getDefaultFileCompression());
+ data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression());
// Always use armor for messages
- data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, mUseArmor);
+ data.setEnableAsciiArmorOutput(mUseArmor);
if (isModeSymmetric()) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
@@ -212,13 +207,12 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
if (passphrase.length() == 0) {
passphrase = null;
}
- data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase);
+ data.setSymmetricPassphrase(passphrase);
} else {
- data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_MASTER_ID, mSigningKeyId);
- data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptionKeyIds);
- data.putString(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_PASSPHRASE, mSigningKeyPassphrase);
- data.putSerializable(KeychainIntentService.ENCRYPT_SIGNATURE_NFC_TIMESTAMP, mNfcTimestamp);
- data.putByteArray(KeychainIntentService.ENCRYPT_SIGNATURE_NFC_HASH, mNfcHash);
+ data.setEncryptionMasterKeyIds(mEncryptionKeyIds);
+ data.setSignatureMasterKeyId(mSigningKeyId);
+ data.setSignaturePassphrase(mSigningKeyPassphrase);
+ data.setNfcState(mNfcHash, mNfcTimestamp);
}
return data;
}
@@ -226,8 +220,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
/**
* Create Intent Chooser but exclude OK's EncryptActivity.
*/
- private Intent sendWithChooserExcludingEncrypt(Message message) {
- Intent prototype = createSendIntent(message);
+ private Intent sendWithChooserExcludingEncrypt() {
+ Intent prototype = createSendIntent();
String title = getString(R.string.title_share_file);
// we don't want to encrypt the encrypted, no inception ;)
@@ -239,7 +233,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
return new ShareHelper(this).createChooserExcluding(prototype, title, blacklist);
}
- private Intent createSendIntent(Message message) {
+ private Intent createSendIntent() {
Intent sendIntent;
// file
if (mOutputUris.size() == 1) {
@@ -252,7 +246,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
sendIntent.setType("application/octet-stream");
if (!isModeSymmetric() && mEncryptionUserIds != null) {
- Set<String> users = new HashSet<String>();
+ Set<String> users = new HashSet<>();
for (String user : mEncryptionUserIds) {
String[] userId = KeyRing.splitUserId(user);
if (userId[1] != null) {
@@ -309,15 +303,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.encrypt_files_activity);
-
// if called with an intent action, do not init drawer navigation
if (ACTION_ENCRYPT_DATA.equals(getIntent().getAction())) {
// lock drawer
- deactivateDrawerNavigation();
+// deactivateDrawerNavigation();
// TODO: back button to key?
} else {
- activateDrawerNavigation(savedInstanceState);
+// activateDrawerNavigation(savedInstanceState);
}
// Handle intent actions
@@ -328,6 +320,11 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
}
@Override
+ protected void initLayout() {
+ setContentView(R.layout.encrypt_files_activity);
+ }
+
+ @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.encrypt_file_activity, menu);
menu.findItem(R.id.check_use_armor).setChecked(mUseArmor);
@@ -379,7 +376,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
String action = intent.getAction();
Bundle extras = intent.getExtras();
String type = intent.getType();
- ArrayList<Uri> uris = new ArrayList<Uri>();
+ ArrayList<Uri> uris = new ArrayList<>();
if (extras == null) {
extras = new Bundle();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index 6961f5ee7..860bd8502 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -36,10 +36,10 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.FileHelper;
-import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import java.io.File;
import java.util.HashMap;
@@ -59,7 +59,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
private View mShareFile;
private ListView mSelectedFiles;
private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter();
- private final Map<Uri, Bitmap> thumbnailCache = new HashMap<Uri, Bitmap>();
+ private final Map<Uri, Bitmap> thumbnailCache = new HashMap<>();
@Override
public void onAttach(Activity activity) {
@@ -224,7 +224,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
@Override
public void onNotifyUpdate() {
// Clear cache if needed
- for (Uri uri : new HashSet<Uri>(thumbnailCache.keySet())) {
+ for (Uri uri : new HashSet<>(thumbnailCache.keySet())) {
if (!mEncryptInterface.getInputUris().contains(uri)) {
thumbnailCache.remove(uri);
}
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 958daa122..2dd861d07 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
@@ -21,7 +21,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuItem;
@@ -30,13 +29,13 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
-import org.sufficientlysecure.keychain.util.Preferences;
-import org.sufficientlysecure.keychain.util.ShareHelper;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.ShareHelper;
import java.util.ArrayList;
import java.util.HashSet;
@@ -121,13 +120,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
@Override
public ArrayList<Uri> getInputUris() {
- if (mInputUris == null) mInputUris = new ArrayList<Uri>();
+ if (mInputUris == null) mInputUris = new ArrayList<>();
return mInputUris;
}
@Override
public ArrayList<Uri> getOutputUris() {
- if (mOutputUris == null) mOutputUris = new ArrayList<Uri>();
+ if (mOutputUris == null) mOutputUris = new ArrayList<>();
return mOutputUris;
}
@@ -169,32 +168,31 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
}
@Override
- protected void onEncryptSuccess(Message message, SignEncryptResult pgpResult) {
+ protected void onEncryptSuccess(SignEncryptResult result) {
if (mShareAfterEncrypt) {
// Share encrypted message/file
- startActivity(sendWithChooserExcludingEncrypt(message));
+ startActivity(sendWithChooserExcludingEncrypt(result.getResultBytes()));
} else {
// Copy to clipboard
- copyToClipboard(message);
- pgpResult.createNotify(EncryptTextActivity.this).show();
+ copyToClipboard(result.getResultBytes());
+ result.createNotify(EncryptTextActivity.this).show();
// Notify.showNotify(EncryptTextActivity.this,
// R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO);
}
}
@Override
- protected Bundle createEncryptBundle() {
+ protected SignEncryptParcel createEncryptBundle() {
// fill values for this action
- Bundle data = new Bundle();
+ SignEncryptParcel data = new SignEncryptParcel();
- data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES);
- data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, mMessage.getBytes());
+ data.setBytes(mMessage.getBytes());
+ data.setCleartextSignature(true);
- data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID,
- Preferences.getPreferences(this).getDefaultMessageCompression());
+ data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression());
// Always use armor for messages
- data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, true);
+ data.setEnableAsciiArmorOutput(true);
if (isModeSymmetric()) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
@@ -202,26 +200,25 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
if (passphrase.length() == 0) {
passphrase = null;
}
- data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase);
+ data.setSymmetricPassphrase(passphrase);
} else {
- data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_MASTER_ID, mSigningKeyId);
- data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptionKeyIds);
- data.putString(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_PASSPHRASE, mSigningKeyPassphrase);
- data.putSerializable(KeychainIntentService.ENCRYPT_SIGNATURE_NFC_TIMESTAMP, mNfcTimestamp);
- data.putByteArray(KeychainIntentService.ENCRYPT_SIGNATURE_NFC_HASH, mNfcHash);
+ data.setEncryptionMasterKeyIds(mEncryptionKeyIds);
+ data.setSignatureMasterKeyId(mSigningKeyId);
+ data.setSignaturePassphrase(mSigningKeyPassphrase);
+ data.setNfcState(mNfcHash, mNfcTimestamp);
}
return data;
}
- private void copyToClipboard(Message message) {
- ClipboardReflection.copyToClipboard(this, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES)));
+ private void copyToClipboard(byte[] resultBytes) {
+ ClipboardReflection.copyToClipboard(this, new String(resultBytes));
}
/**
* Create Intent Chooser but exclude OK's EncryptActivity.
*/
- private Intent sendWithChooserExcludingEncrypt(Message message) {
- Intent prototype = createSendIntent(message);
+ private Intent sendWithChooserExcludingEncrypt(byte[] resultBytes) {
+ Intent prototype = createSendIntent(resultBytes);
String title = getString(R.string.title_share_message);
// we don't want to encrypt the encrypted, no inception ;)
@@ -233,20 +230,21 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
return new ShareHelper(this).createChooserExcluding(prototype, title, blacklist);
}
- private Intent createSendIntent(Message message) {
+ private Intent createSendIntent(byte[] resultBytes) {
Intent sendIntent;
sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
- sendIntent.putExtra(Intent.EXTRA_TEXT, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES)));
+ sendIntent.putExtra(Intent.EXTRA_TEXT, new String(resultBytes));
if (!isModeSymmetric() && mEncryptionUserIds != null) {
- Set<String> users = new HashSet<String>();
+ Set<String> users = new HashSet<>();
for (String user : mEncryptionUserIds) {
String[] userId = KeyRing.splitUserId(user);
if (userId[1] != null) {
users.add(userId[1]);
}
}
+ // pass trough email addresses as extra for email applications
sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()]));
}
return sendIntent;
@@ -288,15 +286,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.encrypt_text_activity);
-
// if called with an intent action, do not init drawer navigation
if (ACTION_ENCRYPT_TEXT.equals(getIntent().getAction())) {
// lock drawer
- deactivateDrawerNavigation();
+// deactivateDrawerNavigation();
// TODO: back button to key?
} else {
- activateDrawerNavigation(savedInstanceState);
+// activateDrawerNavigation(savedInstanceState);
}
// Handle intent actions
@@ -305,6 +301,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
}
@Override
+ protected void initLayout() {
+ setContentView(R.layout.encrypt_text_activity);
+ }
+
+ @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.encrypt_text_activity, menu);
return super.onCreateOptionsMenu(menu);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
index d71c9c465..393e15cfa 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
@@ -19,17 +19,16 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
-public class FirstTimeActivity extends ActionBarActivity {
+public class FirstTimeActivity extends BaseActivity {
View mCreateKey;
View mImportKey;
@@ -43,8 +42,6 @@ public class FirstTimeActivity extends ActionBarActivity {
super.onCreate(savedInstanceState);
- setContentView(R.layout.first_time_activity);
-
mCreateKey = findViewById(R.id.first_time_create_key);
mImportKey = findViewById(R.id.first_time_import_key);
mSkipSetup = findViewById(R.id.first_time_cancel);
@@ -72,7 +69,11 @@ public class FirstTimeActivity extends ActionBarActivity {
startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
}
});
+ }
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.first_time_activity);
}
@Override
@@ -91,7 +92,7 @@ public class FirstTimeActivity extends ActionBarActivity {
private void finishSetup(Intent srcData) {
Preferences prefs = Preferences.getPreferences(this);
prefs.setFirstTime(false);
- Intent intent = new Intent(this, KeyListActivity.class);
+ Intent intent = new Intent(this, MainActivity.class);
// give intent through to display notify
if (srcData != null) {
intent.putExtras(srcData);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
index bbc1e4b1f..2eb35351e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
@@ -20,14 +20,14 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
+import android.view.View;
+
+import com.astuetz.PagerSlidingTabStrip;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
-import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout;
-public class HelpActivity extends ActionBarActivity {
+public class HelpActivity extends BaseActivity {
public static final String EXTRA_SELECTED_TAB = "selected_tab";
public static final int TAB_START = 0;
@@ -44,16 +44,16 @@ public class HelpActivity extends ActionBarActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ActionBar actionBar = getSupportActionBar();
- actionBar.setDisplayShowTitleEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(false);
- actionBar.setHomeButtonEnabled(false);
-
- setContentView(R.layout.help_activity);
+ mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
mViewPager = (ViewPager) findViewById(R.id.pager);
- SlidingTabLayout slidingTabLayout =
- (SlidingTabLayout) findViewById(R.id.sliding_tab_layout);
+ PagerSlidingTabStrip slidingTabLayout =
+ (PagerSlidingTabStrip) findViewById(R.id.sliding_tab_layout);
mTabsAdapter = new PagerTabStripAdapter(this);
mViewPager.setAdapter(mTabsAdapter);
@@ -98,4 +98,9 @@ public class HelpActivity extends ActionBarActivity {
// switch to tab selected by extra
mViewPager.setCurrentItem(selectedTab);
}
+
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.help_activity);
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index dfb7b3056..71f6fd4bf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -17,19 +17,13 @@
package org.sufficientlysecure.keychain.ui;
-import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
-import android.nfc.NdefMessage;
-import android.nfc.NfcAdapter;
-import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
-import android.os.Parcelable;
import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
@@ -51,7 +45,7 @@ import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize
import java.io.IOException;
import java.util.ArrayList;
-public class ImportKeysActivity extends ActionBarActivity {
+public class ImportKeysActivity extends BaseActivity {
public static final String ACTION_IMPORT_KEY = OpenKeychainIntents.IMPORT_KEY;
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = OpenKeychainIntents.IMPORT_KEY_FROM_KEYSERVER;
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT =
@@ -64,9 +58,6 @@ public class ImportKeysActivity extends ActionBarActivity {
// Actions for internal use only:
public static final String ACTION_IMPORT_KEY_FROM_FILE = Constants.INTENT_PREFIX
+ "IMPORT_KEY_FROM_FILE";
- public static final String ACTION_IMPORT_KEY_FROM_NFC = Constants.INTENT_PREFIX
- + "IMPORT_KEY_FROM_NFC";
-
public static final String EXTRA_RESULT = "result";
// only used by ACTION_IMPORT_KEY
@@ -90,8 +81,6 @@ public class ImportKeysActivity extends ActionBarActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.import_keys_activity);
-
mImportButton = findViewById(R.id.import_import);
mImportButton.setOnClickListener(new OnClickListener() {
@Override
@@ -103,6 +92,11 @@ public class ImportKeysActivity extends ActionBarActivity {
handleActions(savedInstanceState, getIntent());
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.import_keys_activity);
+ }
+
protected void handleActions(Bundle savedInstanceState, Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
@@ -113,105 +107,114 @@ public class ImportKeysActivity extends ActionBarActivity {
extras = new Bundle();
}
+ if (action == null) {
+ startCloudFragment(savedInstanceState, null, false);
+ startListFragment(savedInstanceState, null, null, null);
+ return;
+ }
+
if (Intent.ACTION_VIEW.equals(action)) {
// Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
// delegate action to ACTION_IMPORT_KEY
action = ACTION_IMPORT_KEY;
}
- if (ACTION_IMPORT_KEY.equals(action)) {
- /* Keychain's own Actions */
- startFileFragment(savedInstanceState);
+ switch (action) {
+ case ACTION_IMPORT_KEY: {
+ /* Keychain's own Actions */
+ startFileFragment(savedInstanceState);
- if (dataUri != null) {
- // action: directly load data
- startListFragment(savedInstanceState, null, dataUri, null);
- } else if (extras.containsKey(EXTRA_KEY_BYTES)) {
- byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES);
+ if (dataUri != null) {
+ // action: directly load data
+ startListFragment(savedInstanceState, null, dataUri, null);
+ } else if (extras.containsKey(EXTRA_KEY_BYTES)) {
+ byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES);
- // action: directly load data
- startListFragment(savedInstanceState, importData, null, null);
+ // action: directly load data
+ startListFragment(savedInstanceState, importData, null, null);
+ }
+ break;
}
- } else if (ACTION_IMPORT_KEY_FROM_KEYSERVER.equals(action)
- || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(action)
- || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(action)) {
+ case ACTION_IMPORT_KEY_FROM_KEYSERVER:
+ case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE:
+ case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT: {
- // only used for OpenPgpService
- if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) {
- mPendingIntentData = extras.getParcelable(EXTRA_PENDING_INTENT_DATA);
- }
- if (extras.containsKey(EXTRA_QUERY) || extras.containsKey(EXTRA_KEY_ID)) {
- /* simple search based on query or key id */
-
- String query = null;
- if (extras.containsKey(EXTRA_QUERY)) {
- query = extras.getString(EXTRA_QUERY);
- } else if (extras.containsKey(EXTRA_KEY_ID)) {
- long keyId = extras.getLong(EXTRA_KEY_ID, 0);
- if (keyId != 0) {
- query = KeyFormattingUtils.convertKeyIdToHex(keyId);
- }
+ // only used for OpenPgpService
+ if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) {
+ mPendingIntentData = extras.getParcelable(EXTRA_PENDING_INTENT_DATA);
}
+ if (extras.containsKey(EXTRA_QUERY) || extras.containsKey(EXTRA_KEY_ID)) {
+ /* simple search based on query or key id */
+
+ String query = null;
+ if (extras.containsKey(EXTRA_QUERY)) {
+ query = extras.getString(EXTRA_QUERY);
+ } else if (extras.containsKey(EXTRA_KEY_ID)) {
+ long keyId = extras.getLong(EXTRA_KEY_ID, 0);
+ if (keyId != 0) {
+ query = KeyFormattingUtils.convertKeyIdToHex(keyId);
+ }
+ }
- if (query != null && query.length() > 0) {
- // display keyserver fragment with query
- startCloudFragment(savedInstanceState, query, false);
+ if (query != null && query.length() > 0) {
+ // display keyserver fragment with query
+ startCloudFragment(savedInstanceState, query, false);
- // action: search immediately
- startListFragment(savedInstanceState, null, null, query);
- } else {
- Log.e(Constants.TAG, "Query is empty!");
- return;
- }
- } else if (extras.containsKey(EXTRA_FINGERPRINT)) {
- /*
- * search based on fingerprint, here we can enforce a check in the end
- * if the right key has been downloaded
- */
+ // action: search immediately
+ startListFragment(savedInstanceState, null, null, query);
+ } else {
+ Log.e(Constants.TAG, "Query is empty!");
+ return;
+ }
+ } else if (extras.containsKey(EXTRA_FINGERPRINT)) {
+ /*
+ * search based on fingerprint, here we can enforce a check in the end
+ * if the right key has been downloaded
+ */
- String fingerprint = extras.getString(EXTRA_FINGERPRINT);
- if (isFingerprintValid(fingerprint)) {
- String query = "0x" + fingerprint;
+ String fingerprint = extras.getString(EXTRA_FINGERPRINT);
+ if (isFingerprintValid(fingerprint)) {
+ String query = "0x" + fingerprint;
- // display keyserver fragment with query
- startCloudFragment(savedInstanceState, query, true);
+ // display keyserver fragment with query
+ startCloudFragment(savedInstanceState, query, true);
- // action: search immediately
- startListFragment(savedInstanceState, null, null, query);
+ // action: search immediately
+ startListFragment(savedInstanceState, null, null, query);
+ }
+ } else {
+ Log.e(Constants.TAG,
+ "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " +
+ "'fingerprint' extra!"
+ );
+ return;
}
- } else {
- Log.e(Constants.TAG,
- "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " +
- "'fingerprint' extra!"
- );
- return;
+ break;
}
- } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) {
- // NOTE: this only displays the appropriate fragment, no actions are taken
- startFileFragment(savedInstanceState);
-
- // no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
- } else if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) {
- // NOTE: this only displays the appropriate fragment, no actions are taken
- startFileFragment(savedInstanceState);
+ case ACTION_IMPORT_KEY_FROM_FILE: {
+ // NOTE: this only displays the appropriate fragment, no actions are taken
+ startFileFragment(savedInstanceState);
- // no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
- } else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) {
- // NOTE: this only displays the appropriate fragment, no actions are taken
- startFileFragment(savedInstanceState);
- // TODO!!!!!
+ // no immediate actions!
+ startListFragment(savedInstanceState, null, null, null);
+ break;
+ }
+ case ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN: {
+ // NOTE: this only displays the appropriate fragment, no actions are taken
+ startFileFragment(savedInstanceState);
- // no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
- } else {
- startCloudFragment(savedInstanceState, null, false);
- startListFragment(savedInstanceState, null, null, null);
+ // no immediate actions!
+ startListFragment(savedInstanceState, null, null, null);
+ break;
+ }
+ default: {
+ startCloudFragment(savedInstanceState, null, false);
+ startListFragment(savedInstanceState, null, null, null);
+ break;
+ }
}
}
-
private void startListFragment(Bundle savedInstanceState, byte[] bytes, Uri dataUri, String serverQuery) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
@@ -353,7 +356,7 @@ public class ImportKeysActivity extends ActionBarActivity {
// We parcel this iteratively into a file - anything we can
// display here, we should be able to import.
ParcelableFileCache<ParcelableKeyRing> cache =
- new ParcelableFileCache<ParcelableKeyRing>(this, "key_import.pcl");
+ new ParcelableFileCache<>(this, "key_import.pcl");
cache.writeCache(selectedEntries);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -385,7 +388,7 @@ public class ImportKeysActivity extends ActionBarActivity {
data.putString(KeychainIntentService.IMPORT_KEY_SERVER, sls.mCloudPrefs.keyserver);
// get selected key entries
- ArrayList<ParcelableKeyRing> keys = new ArrayList<ParcelableKeyRing>();
+ ArrayList<ParcelableKeyRing> keys = new ArrayList<>();
{
// change the format into ParcelableKeyRing
ArrayList<ImportKeysListEntry> entries = mListFragment.getSelectedEntries();
@@ -413,50 +416,4 @@ public class ImportKeysActivity extends ActionBarActivity {
}
}
- /**
- * NFC
- */
- @Override
- public void onResume() {
- super.onResume();
-
- // Check to see if the Activity started due to an Android Beam
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
- handleActionNdefDiscovered(getIntent());
- } else {
- Log.d(Constants.TAG, "NFC: No NDEF discovered!");
- }
- } else {
- Log.e(Constants.TAG, "Android Beam not supported by Android < 4.1");
- }
- }
-
- /**
- * NFC
- */
- @Override
- public void onNewIntent(Intent intent) {
- // onResume gets called after this to handle the intent
- setIntent(intent);
- }
-
- /**
- * NFC: Parses the NDEF Message from the intent and prints to the TextView
- */
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- void handleActionNdefDiscovered(Intent intent) {
- Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
- // only one message sent during the beam
- NdefMessage msg = (NdefMessage) rawMsgs[0];
- // record 0 contains the MIME type, record 1 is the AAR, if present
- byte[] receivedKeyringBytes = msg.getRecords()[0].getPayload();
-
- Intent importIntent = new Intent(this, ImportKeysActivity.class);
- importIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY);
- importIntent.putExtra(ImportKeysActivity.EXTRA_KEY_BYTES, receivedKeyringBytes);
-
- handleActions(null, importIntent);
- }
-
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
index 03aba344a..91ca93c36 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
@@ -21,6 +21,7 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.preference.PreferenceActivity;
import android.support.v4.app.Fragment;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -36,8 +37,8 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.ContactHelper;
-import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
import java.util.List;
@@ -81,7 +82,7 @@ public class ImportKeysCloudFragment extends Fragment {
namesAndEmails.addAll(ContactHelper.getContactMails(getActivity()));
mQueryEditText.setThreshold(3);
mQueryEditText.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
namesAndEmails
)
@@ -110,11 +111,9 @@ public class ImportKeysCloudFragment extends Fragment {
mConfigButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- Intent i = new Intent(mImportActivity, PreferencesActivity.class);
- // GRR, for some reason I can’t set the Action or I get an incomprehensible
- // exception about “modern two-pane layouts”
- // i.setAction(PreferencesActivity.ACTION_PREFS_CLOUD);
- startActivity(i);
+ Intent intent = new Intent(mImportActivity, SettingsActivity.class);
+ intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, SettingsActivity.CloudSearchPrefsFragment.class.getName());
+ startActivity(intent);
}
});
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index 4fe53fb09..6a6140892 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -113,7 +113,7 @@ public class ImportKeysListFragment extends ListFragment implements
return mAdapter.getSelectedEntries();
} else {
Log.e(Constants.TAG, "Adapter not initialized, returning empty list");
- return new ArrayList<ImportKeysListEntry>();
+ return new ArrayList<>();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
index 5966870df..948da94d8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -17,12 +17,17 @@
package org.sufficientlysecure.keychain.ui;
+import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
+import android.nfc.NdefMessage;
+import android.nfc.NfcAdapter;
+import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
+import android.os.Parcelable;
import android.support.v4.app.FragmentActivity;
import android.widget.Toast;
@@ -48,10 +53,13 @@ import java.util.Locale;
/**
* Proxy activity (just a transparent content view) to scan QR Codes using the Barcode Scanner app
*/
-public class QrCodeScanActivity extends FragmentActivity {
+public class ImportKeysProxyActivity extends FragmentActivity {
public static final String ACTION_QR_CODE_API = OpenKeychainIntents.IMPORT_KEY_FROM_QR_CODE;
public static final String ACTION_SCAN_WITH_RESULT = Constants.INTENT_PREFIX + "SCAN_QR_CODE_WITH_RESULT";
+ public static final String ACTION_SCAN_IMPORT = Constants.INTENT_PREFIX + "SCAN_QR_CODE_IMPORT";
+
+ public static final String EXTRA_FINGERPRINT = "fingerprint";
boolean returnResult;
@@ -73,17 +81,35 @@ public class QrCodeScanActivity extends FragmentActivity {
// Scanning a fingerprint directly with Barcode Scanner, thus we already have scanned
returnResult = false;
- startCertify(dataUri);
+ processScannedContent(dataUri);
+ } else if (ACTION_SCAN_IMPORT.equals(action)) {
+ returnResult = false;
+ IntentIntegrator integrator = new IntentIntegrator(this);
+ integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
+ .setPrompt(getString(R.string.import_qr_code_text))
+ .setResultDisplayDuration(0)
+ .initiateScan();
} else if (ACTION_SCAN_WITH_RESULT.equals(action)) {
- // scan using xzing's Barcode Scanner and return result parcel in OpenKeychain
-
returnResult = true;
- new IntentIntegrator(this).initiateScan();
+ IntentIntegrator integrator = new IntentIntegrator(this);
+ integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
+ .setPrompt(getString(R.string.import_qr_code_text))
+ .setResultDisplayDuration(0)
+ .initiateScan();
} else if (ACTION_QR_CODE_API.equals(action)) {
// scan using xzing's Barcode Scanner from outside OpenKeychain
returnResult = false;
new IntentIntegrator(this).initiateScan();
+ } else if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
+ // Check to see if the Activity started due to an Android Beam
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ returnResult = false;
+ handleActionNdefDiscovered(getIntent());
+ } else {
+ Log.e(Constants.TAG, "Android Beam not supported by Android < 4.1");
+ finish();
+ }
} else {
Log.e(Constants.TAG, "No valid scheme or action given!");
finish();
@@ -95,16 +121,16 @@ public class QrCodeScanActivity extends FragmentActivity {
if (requestCode == IntentIntegratorSupportV4.REQUEST_CODE) {
IntentResult scanResult = IntentIntegratorSupportV4.parseActivityResult(requestCode,
resultCode, data);
- if (scanResult != null && scanResult.getFormatName() != null) {
- String scannedContent = scanResult.getContents();
- Log.d(Constants.TAG, "scannedContent: " + scannedContent);
- startCertify(Uri.parse(scanResult.getContents()));
- } else {
+ if (scanResult == null || scanResult.getFormatName() == null) {
Log.e(Constants.TAG, "scanResult or formatName null! Should not happen!");
finish();
+ return;
}
+ String scannedContent = scanResult.getContents();
+ processScannedContent(scannedContent);
+
return;
}
// if a result has been returned, return it down to other activity
@@ -112,6 +138,42 @@ public class QrCodeScanActivity extends FragmentActivity {
returnResult(data);
} else {
super.onActivityResult(requestCode, resultCode, data);
+ finish();
+ }
+ }
+
+ private void processScannedContent(String content) {
+ Uri uri = Uri.parse(content);
+ processScannedContent(uri);
+ }
+
+ private void processScannedContent(Uri uri) {
+
+ Log.d(Constants.TAG, "scanned: " + uri);
+
+ String fingerprint = null;
+
+ // example: openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282
+ if (uri.getScheme().toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) {
+ fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH);
+ }
+
+ if (fingerprint == null) {
+ SingletonResult result = new SingletonResult(
+ SingletonResult.RESULT_ERROR, OperationResult.LogType.MSG_WRONG_QR_CODE);
+ Intent intent = new Intent();
+ intent.putExtra(SingletonResult.EXTRA_RESULT, result);
+ returnResult(intent);
+ return;
+ }
+
+ if (returnResult) {
+ Intent result = new Intent();
+ result.putExtra(EXTRA_FINGERPRINT, fingerprint);
+ setResult(RESULT_OK, result);
+ finish();
+ } else {
+ importKeys(fingerprint);
}
}
@@ -128,21 +190,28 @@ public class QrCodeScanActivity extends FragmentActivity {
}
}
- public void startCertify(Uri dataUri) {
- // example: openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282
- if (dataUri.getScheme().equals(Constants.FINGERPRINT_SCHEME)) {
- String fingerprint = dataUri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH);
- importKeys(fingerprint);
- } else {
- SingletonResult result = new SingletonResult(
- SingletonResult.RESULT_ERROR, OperationResult.LogType.MSG_WRONG_QR_CODE);
- Intent intent = new Intent();
- intent.putExtra(SingletonResult.EXTRA_RESULT, result);
- returnResult(intent);
- }
+ public void importKeys(byte[] keyringData) {
+
+ ParcelableKeyRing keyEntry = new ParcelableKeyRing(keyringData);
+ ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
+ selectedEntries.add(keyEntry);
+
+ startImportService(selectedEntries);
+
}
public void importKeys(String fingerprint) {
+
+ ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
+ ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
+ selectedEntries.add(keyEntry);
+
+ startImportService(selectedEntries);
+
+ }
+
+ private void startImportService (ArrayList<ParcelableKeyRing> keyRings) {
+
// Message is received after importing is done in KeychainIntentService
KeychainIntentServiceHandler serviceHandler = new KeychainIntentServiceHandler(
this,
@@ -168,7 +237,7 @@ public class QrCodeScanActivity extends FragmentActivity {
return;
}
- if ( ! result.success()) {
+ if (!result.success()) {
// only return if no success...
Intent data = new Intent();
data.putExtras(returnData);
@@ -176,34 +245,32 @@ public class QrCodeScanActivity extends FragmentActivity {
return;
}
- Intent certifyIntent = new Intent(QrCodeScanActivity.this, CertifyKeyActivity.class);
+ Intent certifyIntent = new Intent(ImportKeysProxyActivity.this,
+ CertifyKeyActivity.class);
certifyIntent.putExtra(CertifyKeyActivity.EXTRA_RESULT, result);
- certifyIntent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, result.getImportedMasterKeyIds());
+ certifyIntent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS,
+ result.getImportedMasterKeyIds());
startActivityForResult(certifyIntent, 0);
}
}
};
- // search config
- Preferences prefs = Preferences.getPreferences(this);
- Preferences.CloudSearchPrefs cloudPrefs = new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
-
- // Send all information needed to service to query keys in other thread
- Intent intent = new Intent(this, KeychainIntentService.class);
-
- intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
-
// fill values for this action
Bundle data = new Bundle();
- data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
-
- ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
- ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<ParcelableKeyRing>();
- selectedEntries.add(keyEntry);
+ // search config
+ {
+ Preferences prefs = Preferences.getPreferences(this);
+ Preferences.CloudSearchPrefs cloudPrefs =
+ new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
+ data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
+ }
- data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries);
+ data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, keyRings);
+ // Send all information needed to service to query keys in other thread
+ Intent intent = new Intent(this, KeychainIntentService.class);
+ intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Create a new Messenger for the communication back
@@ -215,6 +282,20 @@ public class QrCodeScanActivity extends FragmentActivity {
// start service with intent
startService(intent);
+
+ }
+
+ /**
+ * NFC: Parses the NDEF Message from the intent and prints to the TextView
+ */
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ void handleActionNdefDiscovered(Intent intent) {
+ Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
+ // only one message sent during the beam
+ NdefMessage msg = (NdefMessage) rawMsgs[0];
+ // record 0 contains the MIME type, record 1 is the AAR, if present
+ byte[] receivedKeyringBytes = msg.getRecords()[0].getPayload();
+ importKeys(receivedKeyringBytes);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
deleted file mode 100644
index 8d26cc955..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.app.ProgressDialog;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Message;
-import android.os.Messenger;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.KeychainDatabase;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.util.ExportHelper;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.Preferences;
-
-import java.io.IOException;
-
-public class KeyListActivity extends DrawerActivity {
-
- public static final int REQUEST_CODE_RESULT_TO_LIST = 1;
-
- ExportHelper mExportHelper;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTitle(R.string.nav_keys);
-
- // if this is the first time show first time activity
- Preferences prefs = Preferences.getPreferences(this);
- if (prefs.isFirstTime()) {
- startActivity(new Intent(this, FirstTimeActivity.class));
- finish();
- return;
- }
-
- mExportHelper = new ExportHelper(this);
-
- setContentView(R.layout.key_list_activity);
-
- Intent data = getIntent();
- // If we got an EXTRA_RESULT in the intent, show the notification
- if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
- OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
- result.createNotify(this).show();
- }
-
- // now setup navigation drawer in DrawerActivity...
- activateDrawerNavigation(savedInstanceState);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.key_list, menu);
-
- if (Constants.DEBUG) {
- menu.findItem(R.id.menu_key_list_debug_cons).setVisible(true);
- menu.findItem(R.id.menu_key_list_debug_read).setVisible(true);
- menu.findItem(R.id.menu_key_list_debug_write).setVisible(true);
- menu.findItem(R.id.menu_key_list_debug_first_time).setVisible(true);
- }
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_key_list_add:
- Intent scanQrCode = new Intent(this, QrCodeScanActivity.class);
- scanQrCode.setAction(QrCodeScanActivity.ACTION_SCAN_WITH_RESULT);
- startActivityForResult(scanQrCode, 0);
- return true;
-
- case R.id.menu_key_list_search_cloud:
- searchCloud();
- return true;
-
- case R.id.menu_key_list_create:
- createKey();
- return true;
-
- case R.id.menu_key_list_import_existing_key:
- Intent intentImportExisting = new Intent(this, ImportKeysActivity.class);
- intentImportExisting.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
- startActivityForResult(intentImportExisting, 0);
- return true;
-
- case R.id.menu_key_list_export:
- mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true);
- return true;
-
- case R.id.menu_key_list_debug_cons:
- consolidate();
- return true;
-
- case R.id.menu_key_list_debug_read:
- try {
- KeychainDatabase.debugBackup(this, true);
- Notify.showNotify(this, "Restored debug_backup.db", Notify.Style.INFO);
- getContentResolver().notifyChange(KeychainContract.KeyRings.CONTENT_URI, null);
- } catch (IOException e) {
- Log.e(Constants.TAG, "IO Error", e);
- Notify.showNotify(this, "IO Error " + e.getMessage(), Notify.Style.ERROR);
- }
- return true;
-
- case R.id.menu_key_list_debug_write:
- try {
- KeychainDatabase.debugBackup(this, false);
- Notify.showNotify(this, "Backup to debug_backup.db completed", Notify.Style.INFO);
- } catch (IOException e) {
- Log.e(Constants.TAG, "IO Error", e);
- Notify.showNotify(this, "IO Error: " + e.getMessage(), Notify.Style.ERROR);
- }
- return true;
-
- case R.id.menu_key_list_debug_first_time:
- Preferences prefs = Preferences.getPreferences(this);
- prefs.setFirstTime(true);
- Intent intent = new Intent(this, FirstTimeActivity.class);
- startActivity(intent);
- finish();
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- private void searchCloud() {
- Intent importIntent = new Intent(this, ImportKeysActivity.class);
- importIntent.putExtra(ImportKeysActivity.EXTRA_QUERY, (String) null); // hack to show only cloud tab
- startActivity(importIntent);
- }
-
- private void createKey() {
- Intent intent = new Intent(this, CreateKeyActivity.class);
- startActivityForResult(intent, 0);
- }
-
- private void consolidate() {
- // Message is received after importing is done in KeychainIntentService
- KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
- this,
- getString(R.string.progress_importing),
- ProgressDialog.STYLE_HORIZONTAL) {
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
- // get returned data bundle
- Bundle returnData = message.getData();
- if (returnData == null) {
- return;
- }
- final ConsolidateResult result =
- returnData.getParcelable(OperationResult.EXTRA_RESULT);
- if (result == null) {
- return;
- }
-
- result.createNotify(KeyListActivity.this).show();
- }
- }
- };
-
- // Send all information needed to service to import key in other thread
- Intent intent = new Intent(this, KeychainIntentService.class);
-
- intent.setAction(KeychainIntentService.ACTION_CONSOLIDATE);
-
- // fill values for this action
- Bundle data = new Bundle();
-
- intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
- intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
-
- // show progress dialog
- saveHandler.showProgressDialog(this);
-
- // start service with intent
- startService(intent);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // if a result has been returned, display a notify
- if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
- OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
- result.createNotify(this).show();
- } else {
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index d0be052d8..b56da463a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.ui;
+import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Context;
@@ -31,62 +32,54 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
-import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.CursorAdapter;
-import android.support.v4.widget.NoScrollableSwipeRefreshLayout;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
-import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
+import com.getbase.floatingactionbutton.FloatingActionButton;
+import com.getbase.floatingactionbutton.FloatingActionsMenu;
+
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
+import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.util.ExportHelper;
-import org.sufficientlysecure.keychain.util.KeyUpdateHelper;
import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainDatabase;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
-import org.sufficientlysecure.keychain.ui.widget.ListAwareSwipeRefreshLayout;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.util.ParcelableFileCache;
+import org.sufficientlysecure.keychain.util.ExportHelper;
+import org.sufficientlysecure.keychain.util.FabContainer;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
-import edu.cmu.cylab.starslinger.exchange.ExchangeActivity;
-import edu.cmu.cylab.starslinger.exchange.ExchangeConfig;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
@@ -96,21 +89,26 @@ import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
*/
public class KeyListFragment extends LoaderFragment
implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener,
- LoaderManager.LoaderCallbacks<Cursor> {
+ LoaderManager.LoaderCallbacks<Cursor>, FabContainer {
+
+ ExportHelper mExportHelper;
private KeyListAdapter mAdapter;
private StickyListHeadersListView mStickyList;
- private ListAwareSwipeRefreshLayout mSwipeRefreshLayout;
// saves the mode object for multiselect, needed for reset at some point
private ActionMode mActionMode = null;
- private boolean mShowAllKeys = true;
-
private String mQuery;
- private SearchView mSearchView;
- boolean hideMenu = false;
+ private FloatingActionsMenu mFab;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mExportHelper = new ExportHelper(getActivity());
+ }
/**
* Load custom layout with StickyListView from library
@@ -123,71 +121,36 @@ public class KeyListFragment extends LoaderFragment
mStickyList = (StickyListHeadersListView) view.findViewById(R.id.key_list_list);
mStickyList.setOnItemClickListener(this);
- mSwipeRefreshLayout = (ListAwareSwipeRefreshLayout) view.findViewById(R.id.key_list_swipe_container);
- mSwipeRefreshLayout.setOnRefreshListener(new NoScrollableSwipeRefreshLayout.OnRefreshListener() {
+ mFab = (FloatingActionsMenu) view.findViewById(R.id.fab_main);
+
+ FloatingActionButton fabQrCode = (FloatingActionButton) view.findViewById(R.id.fab_add_qr_code);
+ FloatingActionButton fabCloud = (FloatingActionButton) view.findViewById(R.id.fab_add_cloud);
+ FloatingActionButton fabFile = (FloatingActionButton) view.findViewById(R.id.fab_add_file);
+
+ fabQrCode.setOnClickListener(new OnClickListener() {
@Override
- public void onRefresh() {
- KeychainIntentServiceHandler finishedHandler = new KeychainIntentServiceHandler(getActivity()) {
- public void handleMessage(Message message) {
- if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
- mSwipeRefreshLayout.setRefreshing(false);
- }
- }
- };
- // new KeyUpdateHelper().updateAllKeys(getActivity(), finishedHandler);
- updateActionbarForSwipe(false);
+ public void onClick(View v) {
+ mFab.collapse();
+ scanQrCode();
}
});
- mSwipeRefreshLayout.setColorScheme(
- R.color.android_purple_dark,
- R.color.android_purple_light,
- R.color.android_purple_dark,
- R.color.android_purple_light);
- mSwipeRefreshLayout.setStickyListHeadersListView(mStickyList);
- mSwipeRefreshLayout.setOnTouchListener(new View.OnTouchListener() {
+ fabCloud.setOnClickListener(new OnClickListener() {
@Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_MOVE) {
- updateActionbarForSwipe(true);
- } else {
- updateActionbarForSwipe(false);
- }
- return false;
+ public void onClick(View v) {
+ mFab.collapse();
+ searchCloud();
+ }
+ });
+ fabFile.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mFab.collapse();
+ importFile();
}
});
- // Just disable for now
- mSwipeRefreshLayout.setIsLocked(true);
- return root;
- }
- private void updateActionbarForSwipe(boolean show) {
- ActionBarActivity activity = (ActionBarActivity) getActivity();
- ActionBar bar = activity.getSupportActionBar();
-
- if (show) {
- bar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
- bar.setDisplayUseLogoEnabled(false);
- bar.setCustomView(R.layout.custom_actionbar);
- TextView title = (TextView) getActivity().findViewById(R.id.custom_actionbar_text);
- title.setText(R.string.swipe_to_update);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- hideMenu = true;
- activity.invalidateOptionsMenu();
- }
- } else {
- bar.setTitle(getActivity().getTitle());
- bar.setDisplayHomeAsUpEnabled(true);
- bar.setDisplayShowTitleEnabled(true);
- bar.setDisplayUseLogoEnabled(true);
- bar.setDisplayShowHomeEnabled(true);
- bar.setDisplayShowCustomEnabled(false);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- hideMenu = false;
- activity.invalidateOptionsMenu();
- }
- }
+ return root;
}
/**
@@ -198,90 +161,91 @@ public class KeyListFragment extends LoaderFragment
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
+ // show app name instead of "keys" from nav drawer
+ getActivity().setTitle(R.string.app_name);
+
mStickyList.setOnItemClickListener(this);
mStickyList.setAreHeadersSticky(true);
mStickyList.setDrawingListUnderStickyHeader(false);
mStickyList.setFastScrollEnabled(true);
/*
- * Multi-selection is only available for Android >= 3.0
+ * Multi-selection
*/
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- mStickyList.setFastScrollAlwaysVisible(true);
+ mStickyList.setFastScrollAlwaysVisible(true);
- mStickyList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
- mStickyList.getWrappedList().setMultiChoiceModeListener(new MultiChoiceModeListener() {
+ mStickyList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+ mStickyList.getWrappedList().setMultiChoiceModeListener(new MultiChoiceModeListener() {
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- android.view.MenuInflater inflater = getActivity().getMenuInflater();
- inflater.inflate(R.menu.key_list_multi, menu);
- mActionMode = mode;
- return true;
- }
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ android.view.MenuInflater inflater = getActivity().getMenuInflater();
+ inflater.inflate(R.menu.key_list_multi, menu);
+ mActionMode = mode;
+ return true;
+ }
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- return false;
- }
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- // get IDs for checked positions as long array
- long[] ids;
+ // get IDs for checked positions as long array
+ long[] ids;
- switch (item.getItemId()) {
- case R.id.menu_key_list_multi_encrypt: {
- ids = mAdapter.getCurrentSelectedMasterKeyIds();
- encrypt(mode, ids);
- break;
- }
- case R.id.menu_key_list_multi_delete: {
- ids = mAdapter.getCurrentSelectedMasterKeyIds();
- showDeleteKeyDialog(mode, ids, mAdapter.isAnySecretSelected());
- break;
- }
- case R.id.menu_key_list_multi_export: {
- ids = mAdapter.getCurrentSelectedMasterKeyIds();
- ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());
- mExportHelper.showExportKeysDialog(ids, Constants.Path.APP_DIR_FILE,
- mAdapter.isAnySecretSelected());
- break;
- }
- case R.id.menu_key_list_multi_select_all: {
- // select all
- for (int i = 0; i < mStickyList.getCount(); i++) {
- mStickyList.setItemChecked(i, true);
- }
- break;
+ switch (item.getItemId()) {
+ case R.id.menu_key_list_multi_encrypt: {
+ ids = mAdapter.getCurrentSelectedMasterKeyIds();
+ encrypt(mode, ids);
+ break;
+ }
+ case R.id.menu_key_list_multi_delete: {
+ ids = mAdapter.getCurrentSelectedMasterKeyIds();
+ showDeleteKeyDialog(mode, ids, mAdapter.isAnySecretSelected());
+ break;
+ }
+ case R.id.menu_key_list_multi_export: {
+ ids = mAdapter.getCurrentSelectedMasterKeyIds();
+ ExportHelper mExportHelper = new ExportHelper(getActivity());
+ mExportHelper.showExportKeysDialog(ids, Constants.Path.APP_DIR_FILE,
+ mAdapter.isAnySecretSelected());
+ break;
+ }
+ case R.id.menu_key_list_multi_select_all: {
+ // select all
+ for (int i = 0; i < mStickyList.getCount(); i++) {
+ mStickyList.setItemChecked(i, true);
}
+ break;
}
- return true;
}
+ return true;
+ }
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- mActionMode = null;
- mAdapter.clearSelection();
- }
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ mActionMode = null;
+ mAdapter.clearSelection();
+ }
- @Override
- public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
- boolean checked) {
- if (checked) {
- mAdapter.setNewSelection(position, checked);
- } else {
- mAdapter.removeSelection(position);
- }
- int count = mStickyList.getCheckedItemCount();
- String keysSelected = getResources().getQuantityString(
- R.plurals.key_list_selected_keys, count, count);
- mode.setTitle(keysSelected);
+ @Override
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
+ boolean checked) {
+ if (checked) {
+ mAdapter.setNewSelection(position, true);
+ } else {
+ mAdapter.removeSelection(position);
}
+ int count = mStickyList.getCheckedItemCount();
+ String keysSelected = getResources().getQuantityString(
+ R.plurals.key_list_selected_keys, count, count);
+ mode.setTitle(keysSelected);
+ }
- });
- }
+ });
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
@@ -340,14 +304,6 @@ public class KeyListFragment extends LoaderFragment
whereArgs[i] = "%" + words[i] + "%";
}
}
- if (!mShowAllKeys) {
- if (where == null) {
- where = "";
- } else {
- where += " AND ";
- }
- where += KeyRings.VERIFIED + " != 0";
- }
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
@@ -368,9 +324,7 @@ public class KeyListFragment extends LoaderFragment
// end action mode, if any
if (mActionMode != null) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- mActionMode.finish();
- }
+ mActionMode.finish();
}
// The list should now be shown.
@@ -400,7 +354,6 @@ public class KeyListFragment extends LoaderFragment
startActivity(viewIntent);
}
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
protected void encrypt(ActionMode mode, long[] masterKeyIds) {
Intent intent = new Intent(getActivity(), EncryptFilesActivity.class);
intent.setAction(EncryptFilesActivity.ACTION_ENCRYPT_DATA);
@@ -414,10 +367,8 @@ public class KeyListFragment extends LoaderFragment
/**
* Show dialog to delete key
*
- * @param masterKeyIds
* @param hasSecret must contain whether the list of masterKeyIds contains a secret key or not
*/
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void showDeleteKeyDialog(final ActionMode mode, long[] masterKeyIds, boolean hasSecret) {
// Can only work on singular secret keys
if (hasSecret && masterKeyIds.length > 1) {
@@ -455,25 +406,27 @@ public class KeyListFragment extends LoaderFragment
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+ inflater.inflate(R.menu.key_list, menu);
+
+ if (Constants.DEBUG) {
+ menu.findItem(R.id.menu_key_list_debug_cons).setVisible(true);
+ menu.findItem(R.id.menu_key_list_debug_read).setVisible(true);
+ menu.findItem(R.id.menu_key_list_debug_write).setVisible(true);
+ menu.findItem(R.id.menu_key_list_debug_first_time).setVisible(true);
+ }
+
// Get the searchview
MenuItem searchItem = menu.findItem(R.id.menu_key_list_search);
- mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
+ SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
// Execute this when searching
- mSearchView.setOnQueryTextListener(this);
-
- View searchPlate = mSearchView.findViewById(android.support.v7.appcompat.R.id.search_plate);
- searchPlate.setBackgroundResource(R.drawable.keychaintheme_searchview_holo_light);
+ searchView.setOnQueryTextListener(this);
// Erase search result without focus
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- hideMenu = true;
- getActivity().invalidateOptionsMenu();
- }
// disable swipe-to-refresh
// mSwipeRefreshLayout.setIsLocked(true);
@@ -485,26 +438,66 @@ public class KeyListFragment extends LoaderFragment
mQuery = null;
getLoaderManager().restartLoader(0, null, KeyListFragment.this);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- hideMenu = false;
- getActivity().invalidateOptionsMenu();
- }
// enable swipe-to-refresh
// mSwipeRefreshLayout.setIsLocked(false);
return true;
}
});
- if (hideMenu) {
- for (int i = 0; i < menu.size(); i++) {
- menu.getItem(i).setVisible(false);
- }
- }
-
super.onCreateOptionsMenu(menu, inflater);
}
@Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+
+ case R.id.menu_key_list_create:
+ createKey();
+ return true;
+
+ case R.id.menu_key_list_export:
+ mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true);
+ return true;
+
+ case R.id.menu_key_list_debug_cons:
+ consolidate();
+ return true;
+
+ case R.id.menu_key_list_debug_read:
+ try {
+ KeychainDatabase.debugBackup(getActivity(), true);
+ Notify.showNotify(getActivity(), "Restored debug_backup.db", Notify.Style.INFO);
+ getActivity().getContentResolver().notifyChange(KeychainContract.KeyRings.CONTENT_URI, null);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IO Error", e);
+ Notify.showNotify(getActivity(), "IO Error " + e.getMessage(), Notify.Style.ERROR);
+ }
+ return true;
+
+ case R.id.menu_key_list_debug_write:
+ try {
+ KeychainDatabase.debugBackup(getActivity(), false);
+ Notify.showNotify(getActivity(), "Backup to debug_backup.db completed", Notify.Style.INFO);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IO Error", e);
+ Notify.showNotify(getActivity(), "IO Error: " + e.getMessage(), Notify.Style.ERROR);
+ }
+ return true;
+
+ case R.id.menu_key_list_debug_first_time:
+ Preferences prefs = Preferences.getPreferences(getActivity());
+ prefs.setFirstTime(true);
+ Intent intent = new Intent(getActivity(), FirstTimeActivity.class);
+ startActivity(intent);
+ getActivity().finish();
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
public boolean onQueryTextSubmit(String s) {
return true;
}
@@ -526,6 +519,105 @@ public class KeyListFragment extends LoaderFragment
return true;
}
+ private void searchCloud() {
+ Intent importIntent = new Intent(getActivity(), ImportKeysActivity.class);
+ importIntent.putExtra(ImportKeysActivity.EXTRA_QUERY, (String) null); // hack to show only cloud tab
+ startActivity(importIntent);
+ }
+
+ private void scanQrCode() {
+ Intent scanQrCode = new Intent(getActivity(), ImportKeysProxyActivity.class);
+ scanQrCode.setAction(ImportKeysProxyActivity.ACTION_SCAN_IMPORT);
+ startActivityForResult(scanQrCode, 0);
+ }
+
+ private void importFile() {
+ Intent intentImportExisting = new Intent(getActivity(), ImportKeysActivity.class);
+ intentImportExisting.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
+ startActivityForResult(intentImportExisting, 0);
+ }
+
+ private void createKey() {
+ Intent intent = new Intent(getActivity(), CreateKeyActivity.class);
+ startActivityForResult(intent, 0);
+ }
+
+ private void consolidate() {
+ // Message is received after importing is done in KeychainIntentService
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
+ getActivity(),
+ getString(R.string.progress_importing),
+ ProgressDialog.STYLE_HORIZONTAL) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+ if (returnData == null) {
+ return;
+ }
+ final ConsolidateResult result =
+ returnData.getParcelable(OperationResult.EXTRA_RESULT);
+ if (result == null) {
+ return;
+ }
+
+ result.createNotify(getActivity()).show();
+ }
+ }
+ };
+
+ // Send all information needed to service to import key in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+
+ intent.setAction(KeychainIntentService.ACTION_CONSOLIDATE);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ saveHandler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // if a result has been returned, display a notify
+ if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
+ OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
+ result.createNotify(getActivity()).show();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ @Override
+ public void fabMoveUp(int height) {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(mFab, "translationY", 0, -height);
+ // we're a little behind, so skip 1/10 of the time
+ anim.setDuration(270);
+ anim.start();
+ }
+
+ @Override
+ public void fabRestorePosition() {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(mFab, "translationY", 0);
+ // we're a little ahead, so wait a few ms
+ anim.setStartDelay(70);
+ anim.setDuration(300);
+ anim.start();
+ }
+
/**
* Implements StickyListHeadersAdapter from library
*/
@@ -533,7 +625,7 @@ public class KeyListFragment extends LoaderFragment
private String mQuery;
private LayoutInflater mInflater;
- private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
+ private HashMap<Integer, Boolean> mSelection = new HashMap<>();
public KeyListAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
@@ -624,13 +716,13 @@ public class KeyListFragment extends LoaderFragment
// Note: order is important!
if (isRevoked) {
- KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_REVOKED, true);
+ KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
h.mStatus.setVisibility(View.VISIBLE);
h.mSlinger.setVisibility(View.GONE);
h.mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
h.mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.bg_gray));
} else if (isExpired) {
- KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_EXPIRED, true);
+ KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
h.mStatus.setVisibility(View.VISIBLE);
h.mSlinger.setVisibility(View.GONE);
h.mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
index 4a2b88518..0de7bb391 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
@@ -19,21 +19,18 @@
package org.sufficientlysecure.keychain.ui;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
-public class LogDisplayActivity extends ActionBarActivity {
+public class LogDisplayActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Inflate a "Done" custom action bar
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogClose(
new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -42,7 +39,10 @@ public class LogDisplayActivity extends ActionBarActivity {
}
}
);
+ }
+ @Override
+ protected void initLayout() {
setContentView(R.layout.log_display_activity);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
index 2baebc83d..b655a7e55 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
@@ -153,11 +153,11 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
switch (subEntry.mType.mLevel) {
case DEBUG: ih.mSecondImg.setBackgroundColor(Color.GRAY); break;
case INFO: ih.mSecondImg.setBackgroundColor(Color.BLACK); break;
- case WARN: ih.mSecondImg.setBackgroundColor(Color.YELLOW); break;
- case ERROR: ih.mSecondImg.setBackgroundColor(Color.RED); break;
- case START: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.emphasis)); break;
- case OK: ih.mSecondImg.setBackgroundColor(Color.GREEN); break;
- case CANCELLED: ih.mSecondImg.setBackgroundColor(Color.RED); break;
+ case WARN: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_orange_light)); break;
+ case ERROR: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
+ case START: ih.mSecondImg.setBackgroundColor(Color.BLACK); break;
+ case OK: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_green_light)); break;
+ case CANCELLED: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
}
} else {
ih.mSecond.setVisibility(View.GONE);
@@ -184,11 +184,11 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
switch (entry.mType.mLevel) {
case DEBUG: ih.mImg.setBackgroundColor(Color.GRAY); break;
case INFO: ih.mImg.setBackgroundColor(Color.BLACK); break;
- case WARN: ih.mImg.setBackgroundColor(Color.YELLOW); break;
- case ERROR: ih.mImg.setBackgroundColor(Color.RED); break;
- case START: ih.mImg.setBackgroundColor(getResources().getColor(R.color.emphasis)); break;
- case OK: ih.mImg.setBackgroundColor(Color.GREEN); break;
- case CANCELLED: ih.mImg.setBackgroundColor(Color.RED); break;
+ case WARN: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_orange_light)); break;
+ case ERROR: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
+ case START: ih.mImg.setBackgroundColor(Color.BLACK); break;
+ case OK: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_green_light)); break;
+ case CANCELLED: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
}
return convertView;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
new file mode 100644
index 000000000..b6b2fcb8a
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+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 it.neokree.materialnavigationdrawer.MaterialNavigationDrawer;
+
+public class MainActivity extends MaterialNavigationDrawer implements FabContainer {
+
+ @Override
+ public void init(Bundle savedInstanceState) {
+ // don't open drawer on first run
+ disableLearningPattern();
+
+// addMultiPaneSupport();
+
+ // set the header image
+ // create and set the header
+ setDrawerHeaderImage(R.drawable.drawer_header);
+
+ // 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)));
+
+ // if this is the first time show first time activity
+ Preferences prefs = Preferences.getPreferences(this);
+ if (prefs.isFirstTime()) {
+ startActivity(new Intent(this, FirstTimeActivity.class));
+ finish();
+ return;
+ }
+
+ Intent data = getIntent();
+ // If we got an EXTRA_RESULT in the intent, show the notification
+ if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
+ OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
+ result.createNotify(this).show();
+ }
+ }
+
+ @Override
+ public void fabMoveUp(int height) {
+ Object fragment = getCurrentSection().getTargetFragment();
+ if (fragment instanceof FabContainer) {
+ ((FabContainer) fragment).fabMoveUp(height);
+ }
+ }
+
+ @Override
+ public void fabRestorePosition() {
+ Object fragment = getCurrentSection().getTargetFragment();
+ if (fragment instanceof FabContainer) {
+ ((FabContainer) fragment).fabRestorePosition();
+ }
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java
index d0e40a9b8..7311f4879 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java
@@ -15,7 +15,6 @@ import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.Build;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.WindowManager;
import android.widget.Toast;
@@ -23,13 +22,11 @@ import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Iso7816TLV;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Locale;
/**
* This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
@@ -38,7 +35,7 @@ import java.util.Locale;
* For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
-public class NfcActivity extends ActionBarActivity {
+public class NfcActivity extends BaseActivity {
// actions
public static final String ACTION_SIGN_HASH = "sign_hash";
@@ -82,8 +79,6 @@ public class NfcActivity extends ActionBarActivity {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- setContentView(R.layout.nfc_activity);
-
Intent intent = getIntent();
Bundle data = intent.getExtras();
String action = intent.getAction();
@@ -93,36 +88,46 @@ public class NfcActivity extends ActionBarActivity {
mKeyId = data.getLong(EXTRA_KEY_ID);
}
- if (ACTION_SIGN_HASH.equals(action)) {
- mAction = action;
- mPin = data.getString(EXTRA_PIN);
- mHashToSign = data.getByteArray(EXTRA_NFC_HASH_TO_SIGN);
- mHashAlgo = data.getInt(EXTRA_NFC_HASH_ALGO);
- mServiceIntent = data.getParcelable(EXTRA_DATA);
-
- Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
- Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
- Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign));
- Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
- } else if (ACTION_DECRYPT_SESSION_KEY.equals(action)) {
- mAction = action;
- mPin = data.getString(EXTRA_PIN);
- mEncryptedSessionKey = data.getByteArray(EXTRA_NFC_ENC_SESSION_KEY);
- mServiceIntent = data.getParcelable(EXTRA_DATA);
-
- Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
- Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
- Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey));
- Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
- } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
- Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!");
- toast("This should not happen! Please create a new bug report that the NFC screen is restarted!");
- finish();
- } else {
- Log.d(Constants.TAG, "Action not supported: " + action);
+ switch (action) {
+ case ACTION_SIGN_HASH:
+ mAction = action;
+ mPin = data.getString(EXTRA_PIN);
+ mHashToSign = data.getByteArray(EXTRA_NFC_HASH_TO_SIGN);
+ mHashAlgo = data.getInt(EXTRA_NFC_HASH_ALGO);
+ mServiceIntent = data.getParcelable(EXTRA_DATA);
+
+ Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
+ Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
+ Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign));
+ Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
+ break;
+ case ACTION_DECRYPT_SESSION_KEY:
+ mAction = action;
+ mPin = data.getString(EXTRA_PIN);
+ mEncryptedSessionKey = data.getByteArray(EXTRA_NFC_ENC_SESSION_KEY);
+ mServiceIntent = data.getParcelable(EXTRA_DATA);
+
+ Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
+ Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
+ Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey));
+ Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
+ break;
+ case NfcAdapter.ACTION_TAG_DISCOVERED:
+ Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!");
+ toast("This should not happen! Please create a new bug report that the NFC screen is restarted!");
+ finish();
+ break;
+ default:
+ Log.d(Constants.TAG, "Action not supported: " + action);
+ break;
}
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.nfc_activity);
+ }
+
/**
* Called when the system is about to start resuming a previous activity,
* disables NFC Foreground Dispatch
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
index cb15dbec2..0ccb206d1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
@@ -15,15 +15,14 @@ import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.Build;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.WindowManager;
import android.widget.Toast;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Iso7816TLV;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Iso7816TLV;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
@@ -36,7 +35,7 @@ import java.nio.ByteBuffer;
* For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
-public class NfcIntentActivity extends ActionBarActivity {
+public class NfcIntentActivity extends BaseActivity {
// special extra for OpenPgpService
public static final String EXTRA_DATA = "data";
@@ -54,8 +53,6 @@ public class NfcIntentActivity extends ActionBarActivity {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- setContentView(R.layout.nfc_activity);
-
Intent intent = getIntent();
Bundle data = intent.getExtras();
String action = intent.getAction();
@@ -87,7 +84,11 @@ public class NfcIntentActivity extends ActionBarActivity {
Log.e(Constants.TAG, "IOException!", e);
finish();
}
+ }
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.nfc_activity);
}
/**
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index 5bface1fb..53fd9cdfd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -41,8 +41,6 @@ import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
-import com.haibison.android.lockpattern.LockPatternActivity;
-
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
@@ -108,20 +106,20 @@ public class PassphraseDialogActivity extends FragmentActivity {
case RESULT_CANCELED:
// The user cancelled the task
break;
- case LockPatternActivity.RESULT_FAILED:
- // The user failed to enter the pattern
- break;
- case LockPatternActivity.RESULT_FORGOT_PATTERN:
- // The user forgot the pattern and invoked your recovery Activity.
- break;
+// case LockPatternActivity.RESULT_FAILED:
+// // The user failed to enter the pattern
+// break;
+// case LockPatternActivity.RESULT_FORGOT_PATTERN:
+// // The user forgot the pattern and invoked your recovery Activity.
+// break;
}
/*
* In any case, there's always a key EXTRA_RETRY_COUNT, which holds
* the number of tries that the user did.
*/
- int retryCount = data.getIntExtra(
- LockPatternActivity.EXTRA_RETRY_COUNT, 0);
+// int retryCount = data.getIntExtra(
+// LockPatternActivity.EXTRA_RETRY_COUNT, 0);
break;
}
@@ -256,9 +254,9 @@ public class PassphraseDialogActivity extends FragmentActivity {
if (keyType == CanonicalizedSecretKey.SecretKeyType.PATTERN) {
// start pattern dialog and show progress circle here...
- Intent patternActivity = new Intent(getActivity(), LockPatternActivity.class);
- patternActivity.putExtra(LockPatternActivity.EXTRA_PATTERN, "123");
- startActivityForResult(patternActivity, REQUEST_CODE_ENTER_PATTERN);
+// Intent patternActivity = new Intent(getActivity(), LockPatternActivity.class);
+// patternActivity.putExtra(LockPatternActivity.EXTRA_PATTERN, "123");
+// startActivityForResult(patternActivity, REQUEST_CODE_ENTER_PATTERN);
mInput.setVisibility(View.GONE);
mProgress.setVisibility(View.VISIBLE);
} else {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
index 93778fd0c..2e838535d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
@@ -43,10 +43,6 @@ import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
-import com.haibison.android.lockpattern.LockPatternFragment;
-import com.haibison.android.lockpattern.LockPatternFragmentOld;
-import com.haibison.android.lockpattern.widget.LockPatternView;
-
import org.sufficientlysecure.keychain.R;
import java.io.IOException;
@@ -56,7 +52,8 @@ import java.util.Arrays;
import java.util.List;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class PassphraseWizardActivity extends FragmentActivity implements LockPatternView.OnPatternListener {
+public class PassphraseWizardActivity extends FragmentActivity {
+//public class PassphraseWizardActivity extends FragmentActivity implements LockPatternView.OnPatternListener {
//create or authenticate
public String selectedAction;
//for lockpattern
@@ -117,10 +114,10 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa
getActionBar().setTitle(R.string.draw_lockpattern);
}
// LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
- LockPatternFragment lpf = LockPatternFragment.newInstance("asd");
+// LockPatternFragment lpf = LockPatternFragment.newInstance("asd");
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
+// FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+// transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
}
public void cancel(View view) {
@@ -205,13 +202,11 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa
writeNFC = false; //just write once
Toast.makeText(this, R.string.nfc_write_succesful, Toast.LENGTH_SHORT).show();
//advance to lockpattern
- LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
+// LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
+// FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+// transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
}
- } catch (IOException e) {
- e.printStackTrace();
- } catch (FormatException e) {
+ } catch (IOException | FormatException e) {
e.printStackTrace();
}
@@ -226,9 +221,9 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa
//passwort matches, go to next view
Toast.makeText(this, R.string.passphrases_match + "!", Toast.LENGTH_SHORT).show();
- LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
+// LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
+// FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+// transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
readNFC = false; //just once
} else {
//passwort doesnt match
@@ -236,9 +231,7 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa
nfc.setText(R.string.nfc_wrong_tag);
}
}
- } catch (IOException e) {
- e.printStackTrace();
- } catch (FormatException e) {
+ } catch (IOException | FormatException e) {
e.printStackTrace();
}
}
@@ -356,26 +349,6 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa
adapter.disableForegroundDispatch(this);
}
- @Override
- public void onPatternStart() {
-
- }
-
- @Override
- public void onPatternCleared() {
-
- }
-
- @Override
- public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
-
- }
-
- @Override
- public void onPatternDetected(List<LockPatternView.Cell> pattern) {
-
- }
-
public static class SelectMethods extends Fragment {
// private OnFragmentInteractionListener mListener;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
index cf0c3eb88..d3c1d971a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
@@ -20,57 +20,56 @@ package org.sufficientlysecure.keychain.ui;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.widget.CardView;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
+import org.sufficientlysecure.keychain.util.Log;
-public class QrCodeViewActivity extends ActionBarActivity {
+public class QrCodeViewActivity extends BaseActivity {
- private ImageView mFingerprintQrCode;
+ private ImageView mQrCode;
+ private CardView mQrCodeLayout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Inflate a "Done" custom action bar
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogClose(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// "Done"
- finish();
+ ActivityCompat.finishAfterTransition(QrCodeViewActivity.this);
}
}
);
- setContentView(R.layout.qr_code_activity);
-
Uri dataUri = getIntent().getData();
if (dataUri == null) {
Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
- finish();
+ ActivityCompat.finishAfterTransition(QrCodeViewActivity.this);
return;
}
- mFingerprintQrCode = (ImageView) findViewById(R.id.qr_code_image);
+ mQrCode = (ImageView) findViewById(R.id.qr_code_image);
+ mQrCodeLayout = (CardView) findViewById(R.id.qr_code_image_layout);
- mFingerprintQrCode.setOnClickListener(new View.OnClickListener() {
+ mQrCodeLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- finish();
+ ActivityCompat.finishAfterTransition(QrCodeViewActivity.this);
}
});
@@ -82,7 +81,7 @@ public class QrCodeViewActivity extends ActionBarActivity {
if (blob == null) {
Log.e(Constants.TAG, "key not found!");
Notify.showNotify(this, R.string.error_key_not_found, Style.ERROR);
- finish();
+ ActivityCompat.finishAfterTransition(QrCodeViewActivity.this);
}
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob);
@@ -91,37 +90,26 @@ public class QrCodeViewActivity extends ActionBarActivity {
// create a minimal size qr code, we can keep this in ram no problem
final Bitmap qrCode = QrCodeUtils.getQRCodeBitmap(qrCodeContent, 0);
- mFingerprintQrCode.getViewTreeObserver().addOnGlobalLayoutListener(
+ mQrCode.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- // create actual bitmap in display dimensions
- Bitmap scaled = Bitmap.createScaledBitmap(qrCode,
- mFingerprintQrCode.getWidth(), mFingerprintQrCode.getWidth(), false);
- mFingerprintQrCode.setImageBitmap(scaled);
- }
- });
+ @Override
+ public void onGlobalLayout() {
+ // create actual bitmap in display dimensions
+ Bitmap scaled = Bitmap.createScaledBitmap(qrCode,
+ mQrCode.getWidth(), mQrCode.getWidth(), false);
+ mQrCode.setImageBitmap(scaled);
+ }
+ });
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
Notify.showNotify(this, R.string.error_key_not_found, Style.ERROR);
- finish();
+ ActivityCompat.finishAfterTransition(QrCodeViewActivity.this);
}
}
@Override
- protected void onResume() {
- super.onResume();
-
- // custom activity transition to get zoom in effect
- this.overridePendingTransition(R.anim.qr_code_zoom_enter, android.R.anim.fade_out);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- // custom activity transition to get zoom out effect
- this.overridePendingTransition(0, R.anim.qr_code_zoom_exit);
+ protected void initLayout() {
+ setContentView(R.layout.qr_code_activity);
}
} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
index 20e1bbe97..d1df2906d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
@@ -27,13 +27,9 @@ import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.FragmentActivity;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.NumberPicker;
-import android.widget.Spinner;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -50,13 +46,12 @@ import org.sufficientlysecure.keychain.util.ParcelableFileCache;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.List;
import edu.cmu.cylab.starslinger.exchange.ExchangeActivity;
import edu.cmu.cylab.starslinger.exchange.ExchangeConfig;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class SafeSlingerActivity extends ActionBarActivity {
+public class SafeSlingerActivity extends BaseActivity {
private static final int REQUEST_CODE_SAFE_SLINGER = 211;
@@ -69,51 +64,17 @@ public class SafeSlingerActivity extends ActionBarActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.safe_slinger_activity);
-
mMasterKeyId = getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, 0);
- // NOTE: there are two versions of this layout, for API >= 11 and one for < 11
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- NumberPicker picker = (NumberPicker) findViewById(R.id.safe_slinger_picker);
- picker.setMinValue(2);
- picker.setMaxValue(10);
- picker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
- @Override
- public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
- mSelectedNumber = newVal;
- }
- });
- } else {
- Spinner spinner = (Spinner) findViewById(R.id.safe_slinger_spinner);
-
- List<String> list = new ArrayList<String>();
- list.add("2");
- list.add("3");
- list.add("4");
- list.add("5");
- list.add("6");
- list.add("7");
- list.add("8");
- list.add("9");
- list.add("10");
-
- ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_spinner_item, list);
- dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spinner.setAdapter(dataAdapter);
- spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mSelectedNumber = position + 2;
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
-
- }
- });
- }
+ NumberPicker picker = (NumberPicker) findViewById(R.id.safe_slinger_picker);
+ picker.setMinValue(2);
+ picker.setMaxValue(10);
+ picker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
+ @Override
+ public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+ mSelectedNumber = newVal;
+ }
+ });
ImageView buttonIcon = (ImageView) findViewById(R.id.safe_slinger_button_image);
buttonIcon.setColorFilter(getResources().getColor(R.color.tertiary_text_light),
@@ -128,6 +89,11 @@ public class SafeSlingerActivity extends ActionBarActivity {
});
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.safe_slinger_activity);
+ }
+
private void startExchange(long masterKeyId, int number) {
// retrieve public key blob and start SafeSlinger
Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(masterKeyId);
@@ -197,7 +163,7 @@ public class SafeSlingerActivity extends ActionBarActivity {
certifyIntent.putExtra(CertifyKeyActivity.EXTRA_RESULT, result);
certifyIntent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, result.getImportedMasterKeyIds());
certifyIntent.putExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, mMasterKeyId);
- startActivityForResult(certifyIntent, KeyListActivity.REQUEST_CODE_RESULT_TO_LIST);
+ startActivityForResult(certifyIntent, 0);
// mExchangeMasterKeyId = null;
}
@@ -221,7 +187,7 @@ public class SafeSlingerActivity extends ActionBarActivity {
// We parcel this iteratively into a file - anything we can
// display here, we should be able to import.
ParcelableFileCache<ParcelableKeyRing> cache =
- new ParcelableFileCache<ParcelableKeyRing>(activity, "key_import.pcl");
+ new ParcelableFileCache<>(activity, "key_import.pcl");
cache.writeCache(it.size(), it.iterator());
// fill values for this action
@@ -249,7 +215,7 @@ public class SafeSlingerActivity extends ActionBarActivity {
}
private static ArrayList<ParcelableKeyRing> getSlingedKeys(Bundle extras) {
- ArrayList<ParcelableKeyRing> list = new ArrayList<ParcelableKeyRing>();
+ ArrayList<ParcelableKeyRing> list = new ArrayList<>();
if (extras != null) {
byte[] d;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
deleted file mode 100644
index 148aa7d67..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.view.View;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
-
-public class SelectPublicKeyActivity extends ActionBarActivity {
-
- // Actions for internal use only:
- public static final String ACTION_SELECT_PUBLIC_KEYS = Constants.INTENT_PREFIX
- + "SELECT_PUBLIC_KEYRINGS";
-
- public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids";
-
- public static final String RESULT_EXTRA_MASTER_KEY_IDS = "master_key_ids";
- public static final String RESULT_EXTRA_USER_IDS = "user_ids";
-
- SelectPublicKeyFragment mSelectFragment;
-
- long mSelectedMasterKeyIds[];
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // ok
- okClicked();
- }
- }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // cancel
- cancelClicked();
- }
- }
- );
-
- setContentView(R.layout.select_public_key_activity);
-
- setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
-
- handleIntent(getIntent());
-
- // Check that the activity is using the layout version with
- // the fragment_container FrameLayout
- if (findViewById(R.id.select_public_key_fragment_container) != null) {
-
- // However, if we're being restored from a previous state,
- // then we don't need to do anything and should return or else
- // we could end up with overlapping fragments.
- if (savedInstanceState != null) {
- return;
- }
-
- // Create an instance of the fragment
- mSelectFragment = SelectPublicKeyFragment.newInstance(mSelectedMasterKeyIds);
-
- // Add the fragment to the 'fragment_container' FrameLayout
- getSupportFragmentManager().beginTransaction()
- .add(R.id.select_public_key_fragment_container, mSelectFragment).commit();
- }
-
- // TODO: reimplement!
- // mFilterLayout = findViewById(R.id.layout_filter);
- // mFilterInfo = (TextView) mFilterLayout.findViewById(R.id.filterInfo);
- // mClearFilterButton = (Button) mFilterLayout.findViewById(R.id.btn_clear);
- //
- // mClearFilterButton.setOnClickListener(new OnClickListener() {
- // public void onClick(View v) {
- // handleIntent(new Intent());
- // }
- // });
-
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- handleIntent(intent);
- }
-
- private void handleIntent(Intent intent) {
- // TODO: reimplement search!
-
- // String searchString = null;
- // if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
- // searchString = intent.getStringExtra(SearchManager.QUERY);
- // if (searchString != null && searchString.trim().length() == 0) {
- // searchString = null;
- // }
- // }
-
- // if (searchString == null) {
- // mFilterLayout.setVisibility(View.GONE);
- // } else {
- // mFilterLayout.setVisibility(View.VISIBLE);
- // mFilterInfo.setText(getString(R.string.filterInfo, searchString));
- // }
-
- // preselected master keys
- mSelectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
- }
-
- private void cancelClicked() {
- setResult(RESULT_CANCELED, null);
- finish();
- }
-
- private void okClicked() {
- Intent data = new Intent();
- data.putExtra(RESULT_EXTRA_MASTER_KEY_IDS, mSelectFragment.getSelectedMasterKeyIds());
- data.putExtra(RESULT_EXTRA_USER_IDS, mSelectFragment.getSelectedUserIds());
- setResult(RESULT_OK, data);
- finish();
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
index af583bf89..afec3bf06 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
@@ -42,7 +42,6 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
@@ -216,7 +215,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
public long[] getSelectedMasterKeyIds() {
// mListView.getCheckedItemIds() would give the row ids of the KeyRings not the master key
// ids!
- Vector<Long> vector = new Vector<Long>();
+ Vector<Long> vector = new Vector<>();
for (int i = 0; i < getListView().getCount(); ++i) {
if (getListView().isItemChecked(i)) {
vector.add(mAdapter.getMasterKeyId(i));
@@ -238,7 +237,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
* @return
*/
public String[] getSelectedUserIds() {
- Vector<String> userIds = new Vector<String>();
+ Vector<String> userIds = new Vector<>();
for (int i = 0; i < getListView().getCount(); ++i) {
if (getListView().isItemChecked(i)) {
userIds.add(mAdapter.getUserId(i));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
index 51fac4779..53986a392 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -17,7 +17,7 @@
package org.sufficientlysecure.keychain.ui;
-import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -27,19 +27,22 @@ import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference;
+import org.sufficientlysecure.keychain.util.Preferences;
import java.util.List;
-@SuppressLint("NewApi")
-public class PreferencesActivity extends PreferenceActivity {
+public class SettingsActivity extends PreferenceActivity {
public static final String ACTION_PREFS_CLOUD = "org.sufficientlysecure.keychain.ui.PREFS_CLOUD";
public static final String ACTION_PREFS_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV";
@@ -54,6 +57,8 @@ public class PreferencesActivity extends PreferenceActivity {
sPreferences = Preferences.getPreferences(this);
super.onCreate(savedInstanceState);
+ setupToolbar();
+
String action = getIntent().getAction();
if (action != null && action.equals(ACTION_PREFS_CLOUD)) {
@@ -64,9 +69,9 @@ public class PreferencesActivity extends PreferenceActivity {
mKeyServerPreference
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
- Intent intent = new Intent(PreferencesActivity.this,
- PreferencesKeyServerActivity.class);
- intent.putExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS,
+ Intent intent = new Intent(SettingsActivity.this,
+ SettingsKeyServerActivity.class);
+ intent.putExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS,
sPreferences.getKeyServers());
startActivityForResult(intent, REQUEST_CODE_KEYSERVER_PREF);
return false;
@@ -130,12 +135,33 @@ public class PreferencesActivity extends PreferenceActivity {
initializeUseNumKeypadForYubikeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN));
- } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
- // Load the legacy preferences headers
- addPreferencesFromResource(R.xml.preference_headers_legacy);
}
}
+ /**
+ * Hack to get Toolbar in PreferenceActivity. See http://stackoverflow.com/a/26614696
+ */
+ private void setupToolbar() {
+ ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
+ LinearLayout content = (LinearLayout) root.getChildAt(0);
+ LinearLayout toolbarContainer = (LinearLayout) View.inflate(this, R.layout.preference_toolbar_activity, null);
+
+ root.removeAllViews();
+ toolbarContainer.addView(content);
+ root.addView(toolbarContainer);
+
+ Toolbar toolbar = (Toolbar) toolbarContainer.findViewById(R.id.toolbar);
+ toolbar.setTitle(R.string.title_preferences);
+ toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp));
+ toolbar.setNavigationOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ //What to do on back clicked
+ finish();
+ }
+ });
+ }
+
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
@@ -144,7 +170,7 @@ public class PreferencesActivity extends PreferenceActivity {
return;
}
String servers[] = data
- .getStringArrayExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS);
+ .getStringArrayExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS);
sPreferences.setKeyServers(servers);
mKeyServerPreference.setSummary(keyserverSummary(this));
break;
@@ -157,7 +183,6 @@ public class PreferencesActivity extends PreferenceActivity {
}
}
- /* Called only on Honeycomb and later */
@Override
public void onBuildHeaders(List<Header> target) {
super.onBuildHeaders(target);
@@ -185,8 +210,8 @@ public class PreferencesActivity extends PreferenceActivity {
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(getActivity(),
- PreferencesKeyServerActivity.class);
- intent.putExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS,
+ SettingsKeyServerActivity.class);
+ intent.putExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS,
sPreferences.getKeyServers());
startActivityForResult(intent, REQUEST_CODE_KEYSERVER_PREF);
return false;
@@ -208,7 +233,7 @@ public class PreferencesActivity extends PreferenceActivity {
return;
}
String servers[] = data
- .getStringArrayExtra(PreferencesKeyServerActivity.EXTRA_KEY_SERVERS);
+ .getStringArrayExtra(SettingsKeyServerActivity.EXTRA_KEY_SERVERS);
sPreferences.setKeyServers(servers);
mKeyServerPreference.setSummary(keyserverSummary(getActivity()));
break;
@@ -287,6 +312,7 @@ public class PreferencesActivity extends PreferenceActivity {
}
}
+ @TargetApi(Build.VERSION_CODES.KITKAT)
protected boolean isValidFragment(String fragmentName) {
return AdvancedPrefsFragment.class.getName().equals(fragmentName)
|| CloudSearchPrefsFragment.class.getName().equals(fragmentName)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
index 2a8ef171c..080dc2495 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PreferencesKeyServerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -28,14 +27,13 @@ import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.ui.widget.Editor;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor;
import java.util.Vector;
-public class PreferencesKeyServerActivity extends ActionBarActivity implements OnClickListener,
+public class SettingsKeyServerActivity extends BaseActivity implements OnClickListener,
EditorListener {
public static final String EXTRA_KEY_SERVERS = "key_servers";
@@ -52,23 +50,19 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
super.onCreate(savedInstanceState);
// Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogDoneClose(R.string.btn_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
- // ok
okClicked();
}
- }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
+ },
+ new View.OnClickListener() {
@Override
public void onClick(View v) {
- // cancel
cancelClicked();
}
- }
- );
-
- setContentView(R.layout.key_server_preference);
+ });
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -102,6 +96,11 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
makeServerList(servers);
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.key_server_preference);
+ }
+
private void makeServerList(String[] servers) {
if (servers != null) {
mEditors.removeAllViews();
@@ -137,7 +136,7 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
}
private Vector<String> serverList() {
- Vector<String> servers = new Vector<String>();
+ Vector<String> servers = new Vector<>();
for (int i = 0; i < mEditors.getChildCount(); ++i) {
KeyServerEditor editor = (KeyServerEditor) mEditors.getChildAt(i);
String tmp = editor.getValue();
@@ -150,7 +149,7 @@ public class PreferencesKeyServerActivity extends ActionBarActivity implements O
private void okClicked() {
Intent data = new Intent();
- Vector<String> servers = new Vector<String>();
+ Vector<String> servers = new Vector<>();
for (int i = 0; i < mEditors.getChildCount(); ++i) {
KeyServerEditor editor = (KeyServerEditor) mEditors.getChildAt(i);
String tmp = editor.getValue();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
index 497486a5e..e19793fd5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
@@ -24,7 +24,6 @@ import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.NavUtils;
-import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
@@ -34,17 +33,17 @@ import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
/**
* Sends the selected public key to a keyserver
*/
-public class UploadKeyActivity extends ActionBarActivity {
+public class UploadKeyActivity extends BaseActivity {
private View mUploadButton;
private Spinner mKeyServerSpinner;
@@ -54,12 +53,10 @@ public class UploadKeyActivity extends ActionBarActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.upload_key_activity);
-
mUploadButton = findViewById(R.id.upload_key_action_upload);
mKeyServerSpinner = (Spinner) findViewById(R.id.upload_key_keyserver);
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
.getKeyServers()
);
@@ -86,6 +83,11 @@ public class UploadKeyActivity extends ActionBarActivity {
}
}
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.upload_key_activity);
+ }
+
private void uploadKey() {
// Send all information needed to service to upload key in other thread
Intent intent = new Intent(this, KeychainIntentService.class);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
index 34c08a6c7..a80503591 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
@@ -27,9 +27,6 @@ import android.support.v4.app.NavUtils;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
-import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
import android.view.MenuItem;
import android.view.View;
@@ -37,19 +34,18 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
-import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.pgp.WrappedSignature;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
import java.util.Date;
-public class ViewCertActivity extends ActionBarActivity
+public class ViewCertActivity extends BaseActivity
implements LoaderManager.LoaderCallbacks<Cursor> {
// These are the rows that we will retrieve.
@@ -86,8 +82,6 @@ public class ViewCertActivity extends ActionBarActivity
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
- setContentView(R.layout.view_cert_activity);
-
mSigneeKey = (TextView) findViewById(R.id.signee_key);
mSigneeUid = (TextView) findViewById(R.id.signee_uid);
mAlgorithm = (TextView) findViewById(R.id.algorithm);
@@ -113,6 +107,11 @@ public class ViewCertActivity extends ActionBarActivity
}
@Override
+ protected void initLayout() {
+ setContentView(R.layout.view_cert_activity);
+ }
+
+ @Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 0bc75b3a9..742cde75c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -18,10 +18,15 @@
package org.sufficientlysecure.keychain.ui;
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.ActivityOptions;
import android.content.Intent;
import android.database.Cursor;
-import android.graphics.PorterDuff;
+import android.graphics.Bitmap;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
@@ -32,62 +37,77 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.Messenger;
import android.provider.ContactsContract;
+import android.provider.Settings;
+import android.support.v4.app.ActivityCompat;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
-import android.support.v4.view.ViewPager;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.widget.CardView;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageButton;
import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
+import com.getbase.floatingactionbutton.FloatingActionButton;
+
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.util.ContactHelper;
-import org.sufficientlysecure.keychain.util.ExportHelper;
-import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
+import org.sufficientlysecure.keychain.operations.results.CertifyResult;
+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.ProviderHelper;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
-import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout;
-import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout.TabColorizer;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
+import org.sufficientlysecure.keychain.ui.widget.AspectRatioImageView;
+import org.sufficientlysecure.keychain.util.ContactHelper;
+import org.sufficientlysecure.keychain.util.ExportHelper;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
+import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
-public class ViewKeyActivity extends ActionBarActivity implements
+public class ViewKeyActivity extends BaseActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
+ static final int REQUEST_QR_FINGERPRINT = 1;
+
ExportHelper mExportHelper;
ProviderHelper mProviderHelper;
protected Uri mDataUri;
- public static final String EXTRA_SELECTED_TAB = "selected_tab";
- public static final int TAB_MAIN = 0;
- public static final int TAB_SHARE = 1;
-
- // view
- private ViewPager mViewPager;
- private SlidingTabLayout mSlidingTabLayout;
- private PagerTabStripAdapter mTabsAdapter;
-
- private LinearLayout mStatusLayout;
+ private TextView mName;
private TextView mStatusText;
private ImageView mStatusImage;
- private View mStatusDivider;
+ private RelativeLayout mBigToolbar;
+
+ private ImageButton mActionEncryptFile;
+ private ImageButton mActionEncryptText;
+ private ImageButton mActionNfc;
+ private FloatingActionButton mFab;
+ private AspectRatioImageView mPhoto;
+ private ImageView mQrCode;
+ private CardView mQrCodeLayout;
// NFC
private NfcAdapter mNfcAdapter;
@@ -98,6 +118,17 @@ public class ViewKeyActivity extends ActionBarActivity implements
private static final int LOADER_ID_UNIFIED = 0;
+ private boolean mIsSecret = false;
+ private boolean mHasEncrypt = false;
+ private boolean mIsVerified = false;
+ private MenuItem mRefreshItem;
+ private boolean mIsRefreshing;
+ private Animation mRotate, mRotateSpin;
+ private View mRefresh;
+ private String mFingerprint;
+ private long mMasterKeyId;
+
+ @SuppressLint("InflateParams")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -105,39 +136,65 @@ public class ViewKeyActivity extends ActionBarActivity implements
mExportHelper = new ExportHelper(this);
mProviderHelper = new ProviderHelper(this);
- // let the actionbar look like Android's contact app
- ActionBar actionBar = getSupportActionBar();
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setIcon(android.R.color.transparent);
- actionBar.setHomeButtonEnabled(true);
+ setTitle(null);
- setContentView(R.layout.view_key_activity);
-
- mStatusLayout = (LinearLayout) findViewById(R.id.view_key_status_layout);
- mStatusText = (TextView) findViewById(R.id.view_key_status_text);
+ mName = (TextView) findViewById(R.id.view_key_name);
+ mStatusText = (TextView) findViewById(R.id.view_key_status);
mStatusImage = (ImageView) findViewById(R.id.view_key_status_image);
- mStatusDivider = findViewById(R.id.view_key_status_divider);
+ mBigToolbar = (RelativeLayout) findViewById(R.id.toolbar_big);
+
+ mActionEncryptFile = (ImageButton) findViewById(R.id.view_key_action_encrypt_files);
+ mActionEncryptText = (ImageButton) findViewById(R.id.view_key_action_encrypt_text);
+ mActionNfc = (ImageButton) findViewById(R.id.view_key_action_nfc);
+ mFab = (FloatingActionButton) findViewById(R.id.fab);
+ mPhoto = (AspectRatioImageView) findViewById(R.id.view_key_photo);
+ mQrCode = (ImageView) findViewById(R.id.view_key_qr_code);
+ mQrCodeLayout = (CardView) findViewById(R.id.view_key_qr_code_layout);
+
+ mRotateSpin = AnimationUtils.loadAnimation(this, R.anim.rotate_spin);
+ mRotateSpin.setAnimationListener(new AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
- mViewPager = (ViewPager) findViewById(R.id.view_key_pager);
- mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.view_key_sliding_tab_layout);
+ }
- mSlidingTabLayout.setCustomTabColorizer(new TabColorizer() {
@Override
- public int getIndicatorColor(int position) {
- return 0xFFAA66CC;
+ public void onAnimationEnd(Animation animation) {
+ mRefreshItem.getActionView().clearAnimation();
+ mRefreshItem.setActionView(null);
+ mRefreshItem.setEnabled(true);
+
+ // this is a deferred call
+ supportInvalidateOptionsMenu();
}
@Override
- public int getDividerColor(int position) {
- return 0;
+ public void onAnimationRepeat(Animation animation) {
+
}
});
+ mRotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
+ mRotate.setRepeatCount(Animation.INFINITE);
+ mRotate.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
- int switchToTab = TAB_MAIN;
- Intent intent = getIntent();
- if (intent.getExtras() != null && intent.getExtras().containsKey(EXTRA_SELECTED_TAB)) {
- switchToTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB);
- }
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+ if (!mIsRefreshing) {
+ mRefreshItem.getActionView().clearAnimation();
+ mRefreshItem.getActionView().startAnimation(mRotateSpin);
+ }
+ }
+ });
+ mRefresh = getLayoutInflater().inflate(R.layout.indeterminate_progress, null);
mDataUri = getIntent().getData();
if (mDataUri == null) {
@@ -155,7 +212,45 @@ public class ViewKeyActivity extends ActionBarActivity implements
}
}
- Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri);
+
+ mActionEncryptFile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ encrypt(mDataUri, false);
+ }
+ });
+ mActionEncryptText.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ encrypt(mDataUri, true);
+ }
+ });
+
+ mFab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mIsSecret) {
+ startSafeSlinger(mDataUri);
+ } else {
+ scanQrCode();
+ }
+ }
+ });
+
+ mQrCodeLayout.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showQrCodeDialog();
+ }
+ });
+
+ mActionNfc.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ invokeNfcBeam();
+ }
+ });
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
@@ -163,35 +258,39 @@ public class ViewKeyActivity extends ActionBarActivity implements
initNfc(mDataUri);
- initTabs(mDataUri);
-
- // switch to tab selected by extra
- mViewPager.setCurrentItem(switchToTab);
+ startFragment(savedInstanceState, mDataUri);
}
- private void initTabs(Uri dataUri) {
- mTabsAdapter = new PagerTabStripAdapter(this);
- mViewPager.setAdapter(mTabsAdapter);
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.view_key_activity);
+ }
- Bundle mainBundle = new Bundle();
- mainBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
- mTabsAdapter.addTab(ViewKeyMainFragment.class,
- mainBundle, getString(R.string.key_view_tab_main));
+ private void startFragment(Bundle savedInstanceState, Uri dataUri) {
+ // However, if we're being restored from a previous state,
+ // then we don't need to do anything and should return or else
+ // we could end up with overlapping fragments.
+ if (savedInstanceState != null) {
+ return;
+ }
- Bundle shareBundle = new Bundle();
- shareBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
- mTabsAdapter.addTab(ViewKeyShareFragment.class,
- shareBundle, getString(R.string.key_view_tab_share));
+ // Create an instance of the fragment
+ ViewKeyFragment frag = ViewKeyFragment.newInstance(dataUri);
- // update layout after operations
- mSlidingTabLayout.setViewPager(mViewPager);
+ // Add the fragment to the 'fragment_container' FrameLayout
+ // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.view_key_fragment, frag)
+ .commitAllowingStateLoss();
+ // do it immediately!
+ getSupportFragmentManager().executePendingTransactions();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.key_view, menu);
-
+ mRefreshItem = menu.findItem(R.id.menu_key_view_refresh);
return true;
}
@@ -200,7 +299,7 @@ public class ViewKeyActivity extends ActionBarActivity implements
try {
switch (item.getItemId()) {
case android.R.id.home: {
- Intent homeIntent = new Intent(this, KeyListActivity.class);
+ Intent homeIntent = new Intent(this, MainActivity.class);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
return true;
@@ -214,9 +313,26 @@ public class ViewKeyActivity extends ActionBarActivity implements
return true;
}
case R.id.menu_key_view_advanced: {
- Intent advancedIntent = new Intent(this, ViewKeyAdvancedActivity.class);
+ Intent advancedIntent = new Intent(this, ViewKeyAdvActivity.class);
advancedIntent.setData(mDataUri);
startActivity(advancedIntent);
+ return true;
+ }
+ case R.id.menu_key_view_refresh: {
+ try {
+ updateFromKeyserver(mDataUri, mProviderHelper);
+ } catch (ProviderHelper.NotFoundException e) {
+ Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
+ }
+ return true;
+ }
+ case R.id.menu_key_view_edit: {
+ editKey(mDataUri);
+ return true;
+ }
+ case R.id.menu_key_view_certify_fingerprint: {
+ certifyFingeprint(mDataUri);
+ return true;
}
}
} catch (ProviderHelper.NotFoundException e) {
@@ -226,6 +342,105 @@ public class ViewKeyActivity extends ActionBarActivity implements
return super.onOptionsItemSelected(item);
}
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem editKey = menu.findItem(R.id.menu_key_view_edit);
+ editKey.setVisible(mIsSecret);
+ MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint);
+ certifyFingerprint.setVisible(!mIsSecret && !mIsVerified);
+
+ return true;
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private void invokeNfcBeam() {
+ // Check for available NFC Adapter
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
+ if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
+ Notify.createNotify(this, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS);
+ startActivity(intentSettings);
+ }
+ }, R.string.menu_nfc_preferences).show();
+
+ return;
+ }
+
+ if (!mNfcAdapter.isNdefPushEnabled()) {
+ Notify.createNotify(this, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
+ startActivity(intentSettings);
+ }
+ }, R.string.menu_beam_preferences).show();
+
+ return;
+ }
+
+ mNfcAdapter.invokeBeam(this);
+ }
+
+ private void scanQrCode() {
+ Intent scanQrCode = new Intent(this, ImportKeysProxyActivity.class);
+ scanQrCode.setAction(ImportKeysProxyActivity.ACTION_SCAN_WITH_RESULT);
+ startActivityForResult(scanQrCode, REQUEST_QR_FINGERPRINT);
+ }
+
+ private void certifyFingeprint(Uri dataUri) {
+ Intent intent = new Intent(this, CertifyFingerprintActivity.class);
+ intent.setData(dataUri);
+
+ startCertifyIntent(intent);
+ }
+
+ private void certifyImmediate() {
+ Intent intent = new Intent(this, CertifyKeyActivity.class);
+ intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{ mMasterKeyId });
+
+ startCertifyIntent(intent);
+ }
+
+ private void startCertifyIntent (Intent intent) {
+ // Message is received after signing is done in KeychainIntentService
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ Bundle data = message.getData();
+ CertifyResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
+
+ result.createNotify(ViewKeyActivity.this).show();
+ }
+ }
+ };
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ startActivityForResult(intent, 0);
+ }
+
+ private void showQrCodeDialog() {
+ Intent qrCodeIntent = new Intent(this, QrCodeViewActivity.class);
+
+ // create the transition animation - the images in the layouts
+ // of both activities are defined with android:transitionName="qr_code"
+ Bundle opts = null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ ActivityOptions options = ActivityOptions
+ .makeSceneTransitionAnimation(this, mQrCodeLayout, "qr_code");
+ opts = options.toBundle();
+ }
+
+ qrCodeIntent.setData(mDataUri);
+ ActivityCompat.startActivity(this, qrCodeIntent, opts);
+ }
+
private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper)
throws ProviderHelper.NotFoundException {
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
@@ -258,7 +473,31 @@ public class ViewKeyActivity extends ActionBarActivity implements
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // if a result has been returned, display a notify
+ if (requestCode == REQUEST_QR_FINGERPRINT && resultCode == Activity.RESULT_OK) {
+
+ // If there is an EXTRA_RESULT, that's an error. Just show it.
+ if (data.hasExtra(OperationResult.EXTRA_RESULT)) {
+ OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
+ result.createNotify(this).show();
+ return;
+ }
+
+ String fp = data.getStringExtra(ImportKeysProxyActivity.EXTRA_FINGERPRINT);
+ if (fp == null) {
+ Notify.createNotify(this, "Error scanning fingerprint!",
+ Notify.LENGTH_LONG, Notify.Style.ERROR).show();
+ return;
+ }
+ if (mFingerprint.equalsIgnoreCase(fp)) {
+ certifyImmediate();
+ } else {
+ Notify.createNotify(this, "Fingerprints did not match!",
+ Notify.LENGTH_LONG, Notify.Style.ERROR).show();
+ }
+
+ return;
+ }
+
if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
result.createNotify(this).show();
@@ -267,6 +506,154 @@ public class ViewKeyActivity extends ActionBarActivity implements
}
}
+ private void encrypt(Uri dataUri, boolean text) {
+ // If there is no encryption key, don't bother.
+ if (!mHasEncrypt) {
+ Notify.showNotify(this, R.string.error_no_encrypt_subkey, Notify.Style.ERROR);
+ return;
+ }
+ try {
+ long keyId = new ProviderHelper(this)
+ .getCachedPublicKeyRing(dataUri)
+ .extractOrGetMasterKeyId();
+ long[] encryptionKeyIds = new long[]{keyId};
+ Intent intent;
+ if (text) {
+ intent = new Intent(this, EncryptTextActivity.class);
+ intent.setAction(EncryptTextActivity.ACTION_ENCRYPT_TEXT);
+ intent.putExtra(EncryptTextActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
+ } else {
+ intent = new Intent(this, EncryptFilesActivity.class);
+ intent.setAction(EncryptFilesActivity.ACTION_ENCRYPT_DATA);
+ intent.putExtra(EncryptFilesActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
+ }
+ // used instead of startActivity set actionbar based on callingPackage
+ startActivityForResult(intent, 0);
+ } catch (PgpKeyNotFoundException e) {
+ Log.e(Constants.TAG, "key not found!", e);
+ }
+ }
+
+ private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper)
+ throws ProviderHelper.NotFoundException {
+
+ mIsRefreshing = true;
+ mRefreshItem.setEnabled(false);
+ mRefreshItem.setActionView(mRefresh);
+ mRefresh.startAnimation(mRotate);
+
+ byte[] blob = (byte[]) providerHelper.getGenericData(
+ KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri),
+ KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
+ String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob);
+
+ ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
+ ArrayList<ParcelableKeyRing> entries = new ArrayList<>();
+ entries.add(keyEntry);
+
+ // Message is received after importing is done in KeychainIntentService
+ KeychainIntentServiceHandler serviceHandler = new KeychainIntentServiceHandler(this) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+
+ mIsRefreshing = false;
+
+ if (returnData == null) {
+ finish();
+ return;
+ }
+ final ImportKeyResult result =
+ returnData.getParcelable(OperationResult.EXTRA_RESULT);
+ result.createNotify(ViewKeyActivity.this).show();
+ }
+ }
+ };
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ // search config
+ {
+ Preferences prefs = Preferences.getPreferences(this);
+ Preferences.CloudSearchPrefs cloudPrefs =
+ new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
+ data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
+ }
+
+ data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, entries);
+
+ // Send all information needed to service to query keys in other thread
+ Intent intent = new Intent(this, 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);
+
+ // show progress dialog
+ serviceHandler.showProgressDialog(this);
+
+ // start service with intent
+ startService(intent);
+
+ }
+
+ private void editKey(Uri dataUri) {
+ Intent editIntent = new Intent(this, EditKeyActivity.class);
+ editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri));
+ startActivityForResult(editIntent, 0);
+ }
+
+ private void startSafeSlinger(Uri dataUri) {
+ long keyId = 0;
+ try {
+ keyId = new ProviderHelper(this)
+ .getCachedPublicKeyRing(dataUri)
+ .extractOrGetMasterKeyId();
+ } catch (PgpKeyNotFoundException e) {
+ Log.e(Constants.TAG, "key not found!", e);
+ }
+ Intent safeSlingerIntent = new Intent(this, SafeSlingerActivity.class);
+ safeSlingerIntent.putExtra(SafeSlingerActivity.EXTRA_MASTER_KEY_ID, keyId);
+ startActivityForResult(safeSlingerIntent, 0);
+ }
+
+ /**
+ * Load QR Code asynchronously and with a fade in animation
+ */
+ private void loadQrCode(final String fingerprint) {
+ AsyncTask<Void, Void, Bitmap> loadTask =
+ new AsyncTask<Void, Void, Bitmap>() {
+ protected Bitmap doInBackground(Void... unused) {
+ String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
+ // render with minimal size
+ return QrCodeUtils.getQRCodeBitmap(qrCodeContent, 0);
+ }
+
+ protected void onPostExecute(Bitmap qrCode) {
+ // scale the image up to our actual size. we do this in code rather
+ // than let the ImageView do this because we don't require filtering.
+ Bitmap scaled = Bitmap.createScaledBitmap(qrCode,
+ mQrCode.getHeight(), mQrCode.getHeight(),
+ false);
+ mQrCode.setImageBitmap(scaled);
+
+ // simple fade-in animation
+ AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
+ anim.setDuration(200);
+ mQrCode.startAnimation(anim);
+ }
+ };
+
+ loadTask.execute();
+ }
+
/**
* NFC: Initialize NFC sharing if OS and device supports it
*/
@@ -357,25 +744,34 @@ public class ViewKeyActivity extends ActionBarActivity implements
}
};
- static final String[] UNIFIED_PROJECTION = new String[]{
+ // These are the rows that we will retrieve.
+ static final String[] PROJECTION = new String[]{
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
KeychainContract.KeyRings.IS_REVOKED,
KeychainContract.KeyRings.EXPIRY,
-
+ KeychainContract.KeyRings.VERIFIED,
+ KeychainContract.KeyRings.HAS_ANY_SECRET,
+ KeychainContract.KeyRings.FINGERPRINT,
+ KeychainContract.KeyRings.HAS_ENCRYPT
};
- static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
- static final int INDEX_UNIFIED_USER_ID = 2;
- static final int INDEX_UNIFIED_IS_REVOKED = 3;
- static final int INDEX_UNIFIED_EXPIRY = 4;
+
+ 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_EXPIRY = 4;
+ static final int INDEX_VERIFIED = 5;
+ static final int INDEX_HAS_ANY_SECRET = 6;
+ static final int INDEX_FINGERPRINT = 7;
+ static final int INDEX_HAS_ENCRYPT = 8;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_UNIFIED: {
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
- return new CursorLoader(this, baseUri, UNIFIED_PROJECTION, null, null, null);
+ return new CursorLoader(this, baseUri, PROJECTION, null, null, null);
}
default:
@@ -383,6 +779,8 @@ public class ViewKeyActivity extends ActionBarActivity implements
}
}
+ int mPreviousColor = 0;
+
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
/* TODO better error handling? May cause problems when a key is deleted,
@@ -398,37 +796,165 @@ public class ViewKeyActivity extends ActionBarActivity implements
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
// get name, email, and comment from USER_ID
- String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_UNIFIED_USER_ID));
+ String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
if (mainUserId[0] != null) {
- setTitle(mainUserId[0]);
+ mName.setText(mainUserId[0]);
} else {
- setTitle(R.string.user_id_no_name);
+ mName.setText(R.string.user_id_no_name);
}
- // get key id from MASTER_KEY_ID
- long masterKeyId = data.getLong(INDEX_UNIFIED_MASTER_KEY_ID);
- getSupportActionBar().setSubtitle(KeyFormattingUtils.beautifyKeyIdWithPrefix(this, masterKeyId));
+ mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
+ mFingerprint = KeyFormattingUtils.convertFingerprintToHex(data.getBlob(INDEX_FINGERPRINT));
+
+ mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
+ mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
+ boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
+ boolean isExpired = !data.isNull(INDEX_EXPIRY)
+ && new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
+ mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
+
+ // if the refresh animation isn't playing
+ if (!mRotate.hasStarted() && !mRotateSpin.hasStarted()) {
+ // re-create options menu based on mIsSecret, mIsVerified
+ supportInvalidateOptionsMenu();
+ // this is done at the end of the animation otherwise
+ }
- boolean isRevoked = data.getInt(INDEX_UNIFIED_IS_REVOKED) > 0;
- boolean isExpired = !data.isNull(INDEX_UNIFIED_EXPIRY)
- && new Date(data.getLong(INDEX_UNIFIED_EXPIRY) * 1000).before(new Date());
+ AsyncTask<String, Void, Bitmap> photoTask =
+ new AsyncTask<String, Void, Bitmap>() {
+ protected Bitmap doInBackground(String... fingerprint) {
+ return ContactHelper.photoFromFingerprint(getContentResolver(), fingerprint[0]);
+ }
+
+ protected void onPostExecute(Bitmap photo) {
+ mPhoto.setImageBitmap(photo);
+ mPhoto.setVisibility(View.VISIBLE);
+ }
+ };
// Note: order is important
+ int color;
if (isRevoked) {
mStatusText.setText(R.string.view_key_revoked);
- KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, KeyFormattingUtils.STATE_REVOKED);
- mStatusDivider.setVisibility(View.VISIBLE);
- mStatusLayout.setVisibility(View.VISIBLE);
+ mStatusImage.setVisibility(View.VISIBLE);
+ KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
+ KeyFormattingUtils.STATE_REVOKED, R.color.icons, true);
+ color = getResources().getColor(R.color.android_red_light);
+
+ mActionEncryptFile.setVisibility(View.GONE);
+ mActionEncryptText.setVisibility(View.GONE);
+ mActionNfc.setVisibility(View.GONE);
+ mFab.setVisibility(View.GONE);
+ mQrCodeLayout.setVisibility(View.GONE);
} else if (isExpired) {
- mStatusText.setText(R.string.view_key_expired);
- KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, KeyFormattingUtils.STATE_EXPIRED);
- mStatusDivider.setVisibility(View.VISIBLE);
- mStatusLayout.setVisibility(View.VISIBLE);
+ if (mIsSecret) {
+ mStatusText.setText(R.string.view_key_expired_secret);
+ } else {
+ mStatusText.setText(R.string.view_key_expired);
+ }
+ mStatusImage.setVisibility(View.VISIBLE);
+ KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
+ KeyFormattingUtils.STATE_EXPIRED, R.color.icons, true);
+ color = getResources().getColor(R.color.android_red_light);
+
+ mActionEncryptFile.setVisibility(View.GONE);
+ mActionEncryptText.setVisibility(View.GONE);
+ mActionNfc.setVisibility(View.GONE);
+ mFab.setVisibility(View.GONE);
+ mQrCodeLayout.setVisibility(View.GONE);
+ } else if (mIsSecret) {
+ mStatusText.setText(R.string.view_key_my_key);
+ mStatusImage.setVisibility(View.GONE);
+ color = getResources().getColor(R.color.primary);
+ photoTask.execute(mFingerprint);
+ loadQrCode(mFingerprint);
+ mQrCodeLayout.setVisibility(View.VISIBLE);
+
+ // and place leftOf qr code
+ RelativeLayout.LayoutParams nameParams = (RelativeLayout.LayoutParams)
+ mName.getLayoutParams();
+ // remove right margin
+ nameParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0);
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ nameParams.setMarginEnd(0);
+ }
+ nameParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
+ mName.setLayoutParams(nameParams);
+
+ RelativeLayout.LayoutParams statusParams = (RelativeLayout.LayoutParams)
+ mStatusText.getLayoutParams();
+ statusParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0);
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ statusParams.setMarginEnd(0);
+ }
+ statusParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
+ mStatusText.setLayoutParams(statusParams);
+
+ mActionEncryptFile.setVisibility(View.VISIBLE);
+ mActionEncryptText.setVisibility(View.VISIBLE);
+
+ // invokeBeam is available from API 21
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ mActionNfc.setVisibility(View.VISIBLE);
+ } else {
+ mActionNfc.setVisibility(View.GONE);
+ }
+ mFab.setVisibility(View.VISIBLE);
+ mFab.setIconDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp));
} else {
- mStatusDivider.setVisibility(View.GONE);
- mStatusLayout.setVisibility(View.GONE);
+ mActionEncryptFile.setVisibility(View.VISIBLE);
+ mActionEncryptText.setVisibility(View.VISIBLE);
+ mQrCodeLayout.setVisibility(View.GONE);
+ mActionNfc.setVisibility(View.GONE);
+
+ if (mIsVerified) {
+ mStatusText.setText(R.string.view_key_verified);
+ mStatusImage.setVisibility(View.VISIBLE);
+ KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
+ KeyFormattingUtils.STATE_VERIFIED, R.color.icons, true);
+ color = getResources().getColor(R.color.primary);
+ photoTask.execute(mFingerprint);
+
+ mFab.setVisibility(View.GONE);
+ } else {
+ mStatusText.setText(R.string.view_key_unverified);
+ mStatusImage.setVisibility(View.VISIBLE);
+ KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
+ KeyFormattingUtils.STATE_UNVERIFIED, R.color.icons, true);
+ color = getResources().getColor(R.color.android_orange_light);
+
+ mFab.setVisibility(View.VISIBLE);
+ }
}
+ if (mPreviousColor == 0 || mPreviousColor == color) {
+ mToolbar.setBackgroundColor(color);
+ mStatusBar.setBackgroundColor(color);
+ mBigToolbar.setBackgroundColor(color);
+ mPreviousColor = color;
+ } else {
+ ObjectAnimator colorFade1 =
+ ObjectAnimator.ofObject(mToolbar, "backgroundColor",
+ new ArgbEvaluator(), mPreviousColor, color);
+ ObjectAnimator colorFade2 =
+ ObjectAnimator.ofObject(mStatusBar, "backgroundColor",
+ new ArgbEvaluator(), mPreviousColor, color);
+ ObjectAnimator colorFade3 =
+ ObjectAnimator.ofObject(mBigToolbar, "backgroundColor",
+ new ArgbEvaluator(), mPreviousColor, color);
+
+ colorFade1.setDuration(1200);
+ colorFade2.setDuration(1200);
+ colorFade3.setDuration(1200);
+ colorFade1.start();
+ colorFade2.start();
+ colorFade3.start();
+ mPreviousColor = color;
+ }
+
+ //noinspection deprecation
+ mStatusImage.setAlpha(80);
+
break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
new file mode 100644
index 000000000..9d79b377c
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.support.v4.view.ViewPager;
+import android.view.View;
+import android.widget.Toast;
+
+import com.astuetz.PagerSlidingTabStrip;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.ContactHelper;
+import org.sufficientlysecure.keychain.util.ExportHelper;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.util.Date;
+
+public class ViewKeyAdvActivity extends BaseActivity implements
+ LoaderManager.LoaderCallbacks<Cursor> {
+
+ ExportHelper mExportHelper;
+ ProviderHelper mProviderHelper;
+
+ protected Uri mDataUri;
+
+ public static final String EXTRA_SELECTED_TAB = "selected_tab";
+ public static final int TAB_MAIN = 0;
+ public static final int TAB_SHARE = 1;
+
+ // view
+ private ViewPager mViewPager;
+ private PagerSlidingTabStrip mSlidingTabLayout;
+ private PagerTabStripAdapter mTabsAdapter;
+
+ private static final int LOADER_ID_UNIFIED = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setFullScreenDialogClose(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+
+ mExportHelper = new ExportHelper(this);
+ mProviderHelper = new ProviderHelper(this);
+
+ mViewPager = (ViewPager) findViewById(R.id.view_key_pager);
+ mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.view_key_sliding_tab_layout);
+
+ int switchToTab = TAB_MAIN;
+ Intent intent = getIntent();
+ if (intent.getExtras() != null && intent.getExtras().containsKey(EXTRA_SELECTED_TAB)) {
+ switchToTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB);
+ }
+
+ mDataUri = getIntent().getData();
+ if (mDataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be uri of key!");
+ finish();
+ return;
+ }
+ if (mDataUri.getHost().equals(ContactsContract.AUTHORITY)) {
+ mDataUri = ContactHelper.dataUriFromContactUri(this, mDataUri);
+ if (mDataUri == null) {
+ Log.e(Constants.TAG, "Contact Data missing. Should be uri of key!");
+ Toast.makeText(this, R.string.error_contacts_key_id_missing, Toast.LENGTH_LONG).show();
+ finish();
+ return;
+ }
+ }
+
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+
+ // Prepare the loaders. Either re-connect with an existing ones,
+ // or start new ones.
+ getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
+
+ initTabs(mDataUri);
+
+ // switch to tab selected by extra
+ mViewPager.setCurrentItem(switchToTab);
+ }
+
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.view_key_adv_activity);
+ }
+
+ private void initTabs(Uri dataUri) {
+ mTabsAdapter = new PagerTabStripAdapter(this);
+ mViewPager.setAdapter(mTabsAdapter);
+
+ Bundle shareBundle = new Bundle();
+ shareBundle.putParcelable(ViewKeyAdvUserIdsFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ViewKeyAdvShareFragment.class,
+ shareBundle, getString(R.string.key_view_tab_share));
+
+ Bundle userIdsBundle = new Bundle();
+ userIdsBundle.putParcelable(ViewKeyAdvUserIdsFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ViewKeyAdvUserIdsFragment.class,
+ userIdsBundle, getString(R.string.section_user_ids));
+
+ Bundle keysBundle = new Bundle();
+ keysBundle.putParcelable(ViewKeyAdvSubkeysFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ViewKeyAdvSubkeysFragment.class,
+ keysBundle, getString(R.string.key_view_tab_keys));
+
+ Bundle certsBundle = new Bundle();
+ certsBundle.putParcelable(ViewKeyAdvCertsFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ViewKeyAdvCertsFragment.class,
+ certsBundle, getString(R.string.key_view_tab_certs));
+
+ Bundle trustBundle = new Bundle();
+ trustBundle.putParcelable(ViewKeyTrustFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ViewKeyTrustFragment.class,
+ trustBundle, getString(R.string.key_view_tab_keybase));
+
+ // update layout after operations
+ mSlidingTabLayout.setViewPager(mViewPager);
+ }
+
+ // These are the rows that we will retrieve.
+ static final String[] PROJECTION = new String[]{
+ KeychainContract.KeyRings._ID,
+ KeychainContract.KeyRings.MASTER_KEY_ID,
+ KeychainContract.KeyRings.USER_ID,
+ KeychainContract.KeyRings.IS_REVOKED,
+ KeychainContract.KeyRings.EXPIRY,
+ KeychainContract.KeyRings.VERIFIED,
+ KeychainContract.KeyRings.HAS_ANY_SECRET
+ };
+
+ 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_EXPIRY = 4;
+ static final int INDEX_VERIFIED = 5;
+ static final int INDEX_HAS_ANY_SECRET = 6;
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ switch (id) {
+ case LOADER_ID_UNIFIED: {
+ Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
+ return new CursorLoader(this, baseUri, PROJECTION, null, null, null);
+ }
+
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ /* TODO better error handling? May cause problems when a key is deleted,
+ * because the notification triggers faster than the activity closes.
+ */
+ // Avoid NullPointerExceptions...
+ if (data.getCount() == 0) {
+ return;
+ }
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ switch (loader.getId()) {
+ case LOADER_ID_UNIFIED: {
+ if (data.moveToFirst()) {
+ // get name, email, and comment from USER_ID
+ String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
+ if (mainUserId[0] != null) {
+ setTitle(mainUserId[0]);
+ } else {
+ setTitle(R.string.user_id_no_name);
+ }
+
+ // get key id from MASTER_KEY_ID
+ long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
+ getSupportActionBar().setSubtitle(KeyFormattingUtils.beautifyKeyIdWithPrefix(this, masterKeyId));
+
+ boolean isSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
+ boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
+ boolean isExpired = !data.isNull(INDEX_EXPIRY)
+ && new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
+ boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
+
+ // Note: order is important
+ int color;
+ if (isRevoked || isExpired) {
+ color = getResources().getColor(R.color.android_red_light);
+ } else if (isSecret) {
+ color = getResources().getColor(R.color.primary);
+ } else {
+ if (isVerified) {
+ color = getResources().getColor(R.color.primary);
+ } else {
+ color = getResources().getColor(R.color.android_orange_light);
+ }
+ }
+ mToolbar.setBackgroundColor(color);
+ mStatusBar.setBackgroundColor(color);
+ mSlidingTabLayout.setBackgroundColor(color);
+
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // if a result has been returned, display a notify
+ if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
+ OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
+ result.createNotify(this).show();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java
index 61bd126ce..90d7a400f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
@@ -30,7 +30,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.ListView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
@@ -39,7 +38,6 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.WrappedSignature;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
-import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
@@ -47,23 +45,16 @@ import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
-public class ViewKeyAdvancedFragment extends LoaderFragment implements
+public class ViewKeyAdvCertsFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
public static final String ARG_DATA_URI = "data_uri";
- private ListView mSubkeysList;
- private SubkeysAdapter mSubkeysAdapter;
-
private StickyListHeadersListView mStickyList;
private CertListAdapter mCertsAdapter;
- private Uri mDataUriSubkeys;
private Uri mDataUriCerts;
- private static final int LOADER_SUBKEYS = 1;
- private static final int LOADER_CERTS = 2;
-
// These are the rows that we will retrieve.
static final String[] CERTS_PROJECTION = new String[]{
KeychainContract.Certs._ID,
@@ -86,8 +77,8 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
/**
* Creates new instance of this fragment
*/
- public static ViewKeyAdvancedFragment newInstance(Uri dataUri) {
- ViewKeyAdvancedFragment frag = new ViewKeyAdvancedFragment();
+ public static ViewKeyAdvCertsFragment newInstance(Uri dataUri) {
+ ViewKeyAdvCertsFragment frag = new ViewKeyAdvCertsFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_DATA_URI, dataUri);
@@ -99,9 +90,8 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
- View view = inflater.inflate(R.layout.view_key_advanced_fragment, getContainer());
+ View view = inflater.inflate(R.layout.view_key_adv_certs_fragment, getContainer());
- mSubkeysList = (ListView) view.findViewById(R.id.keys);
mStickyList = (StickyListHeadersListView) view.findViewById(R.id.certs_list);
return root;
@@ -122,7 +112,6 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
}
private void loadData(Uri dataUri) {
- mDataUriSubkeys = KeychainContract.Keys.buildKeysUri(dataUri);
mDataUriCerts = KeychainContract.Certs.buildCertsUri(dataUri);
mStickyList.setAreHeadersSticky(true);
@@ -132,34 +121,23 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
mStickyList.setEmptyView(getActivity().findViewById(R.id.empty));
// Create an empty adapter we will use to display the loaded data.
- mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
- mSubkeysList.setAdapter(mSubkeysAdapter);
-
mCertsAdapter = new CertListAdapter(getActivity(), null);
mStickyList.setAdapter(mCertsAdapter);
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
- getLoaderManager().initLoader(LOADER_SUBKEYS, null, this);
- getLoaderManager().initLoader(LOADER_CERTS, null, this);
+ getLoaderManager().initLoader(0, null, this);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
setContentShown(false);
- switch (id) {
- case LOADER_SUBKEYS:
- return new CursorLoader(getActivity(), mDataUriSubkeys,
- SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null);
-
- case LOADER_CERTS:
- // Now create and return a CursorLoader that will take care of
- // creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), mDataUriCerts,
- CERTS_PROJECTION, null, null, CERTS_SORT_ORDER);
-
- default:
- return null;
- }
+
+
+ // Now create and return a CursorLoader that will take care of
+ // creating a Cursor for the data being displayed.
+ return new CursorLoader(getActivity(), mDataUriCerts,
+ CERTS_PROJECTION, null, null, CERTS_SORT_ORDER);
+
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
@@ -170,15 +148,8 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
- switch (loader.getId()) {
- case LOADER_SUBKEYS:
- mSubkeysAdapter.swapCursor(data);
- break;
- case LOADER_CERTS:
- mCertsAdapter.swapCursor(data);
- mStickyList.setAdapter(mCertsAdapter);
- break;
- }
+ mCertsAdapter.swapCursor(data);
+ mStickyList.setAdapter(mCertsAdapter);
// TODO: maybe show not before both are loaded!
setContentShown(true);
@@ -189,14 +160,7 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
* We need to make sure we are no longer using it.
*/
public void onLoaderReset(Loader<Cursor> loader) {
- switch (loader.getId()) {
- case LOADER_SUBKEYS:
- mSubkeysAdapter.swapCursor(null);
- break;
- case LOADER_CERTS:
- mCertsAdapter.swapCursor(null);
- break;
- }
+ mCertsAdapter.swapCursor(null);
}
/**
@@ -307,7 +271,7 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(R.layout.view_key_certs_item, parent, false);
+ return mInflater.inflate(R.layout.view_key_adv_certs_item, parent, false);
}
/**
@@ -322,7 +286,7 @@ public class ViewKeyAdvancedFragment extends LoaderFragment implements
HeaderViewHolder holder;
if (convertView == null) {
holder = new HeaderViewHolder();
- convertView = mInflater.inflate(R.layout.view_key_certs_header, parent, false);
+ convertView = mInflater.inflate(R.layout.view_key_adv_certs_header, parent, false);
holder.text = (TextView) convertView.findViewById(R.id.stickylist_header_text);
holder.count = (TextView) convertView.findViewById(R.id.certs_num);
convertView.setTag(holder);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
index aa260b654..8d0a2dd1d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -17,7 +17,7 @@
package org.sufficientlysecure.keychain.ui;
-import android.annotation.TargetApi;
+import android.app.ActivityOptions;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -26,10 +26,11 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
-import android.provider.Settings;
+import android.support.v4.app.ActivityCompat;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
+import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -47,7 +48,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
@@ -56,20 +56,19 @@ import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
-public class ViewKeyShareFragment extends LoaderFragment implements
+public class ViewKeyAdvShareFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String ARG_DATA_URI = "uri";
private TextView mFingerprint;
- private ImageView mFingerprintQrCode;
+ private ImageView mQrCode;
+ private CardView mQrCodeLayout;
private View mFingerprintShareButton;
private View mFingerprintClipboardButton;
private View mKeyShareButton;
private View mKeyClipboardButton;
private ImageButton mKeySafeSlingerButton;
- private View mNfcHelpButton;
- private View mNfcPrefsButton;
private View mKeyUploadButton;
ProviderHelper mProviderHelper;
@@ -81,31 +80,24 @@ public class ViewKeyShareFragment extends LoaderFragment implements
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
- View view = inflater.inflate(R.layout.view_key_share_fragment, getContainer());
+ View view = inflater.inflate(R.layout.view_key_adv_share_fragment, getContainer());
- mProviderHelper = new ProviderHelper(ViewKeyShareFragment.this.getActivity());
+ mProviderHelper = new ProviderHelper(ViewKeyAdvShareFragment.this.getActivity());
mFingerprint = (TextView) view.findViewById(R.id.view_key_fingerprint);
- mFingerprintQrCode = (ImageView) view.findViewById(R.id.view_key_fingerprint_qr_code_image);
+ mQrCode = (ImageView) view.findViewById(R.id.view_key_qr_code);
+ mQrCodeLayout = (CardView) view.findViewById(R.id.view_key_qr_code_layout);
mFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share);
mFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard);
mKeyShareButton = view.findViewById(R.id.view_key_action_key_share);
mKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);
mKeySafeSlingerButton = (ImageButton) view.findViewById(R.id.view_key_action_key_safeslinger);
- mNfcHelpButton = view.findViewById(R.id.view_key_action_nfc_help);
- mNfcPrefsButton = view.findViewById(R.id.view_key_action_nfc_prefs);
mKeyUploadButton = view.findViewById(R.id.view_key_action_upload);
mKeySafeSlingerButton.setColorFilter(getResources().getColor(R.color.tertiary_text_light),
PorterDuff.Mode.SRC_IN);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- mNfcPrefsButton.setVisibility(View.VISIBLE);
- } else {
- mNfcPrefsButton.setVisibility(View.GONE);
- }
-
- mFingerprintQrCode.setOnClickListener(new View.OnClickListener() {
+ mQrCodeLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showQrCodeDialog();
@@ -142,18 +134,6 @@ public class ViewKeyShareFragment extends LoaderFragment implements
startSafeSlinger(mDataUri);
}
});
- mNfcHelpButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showNfcHelpDialog();
- }
- });
- mNfcPrefsButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showNfcPrefs();
- }
- });
mKeyUploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -228,10 +208,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements
}
startActivity(Intent.createChooser(sendIntent, title));
}
- } catch (PgpGeneralException e) {
- Log.e(Constants.TAG, "error processing key!", e);
- Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR);
- } catch (IOException e) {
+ } catch (PgpGeneralException | IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR);
} catch (ProviderHelper.NotFoundException e) {
@@ -242,20 +219,18 @@ public class ViewKeyShareFragment extends LoaderFragment implements
private void showQrCodeDialog() {
Intent qrCodeIntent = new Intent(getActivity(), QrCodeViewActivity.class);
- qrCodeIntent.setData(mDataUri);
- startActivity(qrCodeIntent);
- }
- private void showNfcHelpDialog() {
- ShareNfcDialogFragment dialog = ShareNfcDialogFragment.newInstance();
- dialog.show(getActivity().getSupportFragmentManager(), "shareNfcDialog");
- }
+ // create the transition animation - the images in the layouts
+ // of both activities are defined with android:transitionName="qr_code"
+ Bundle opts = null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ ActivityOptions options = ActivityOptions
+ .makeSceneTransitionAnimation(getActivity(), mQrCodeLayout, "qr_code");
+ opts = options.toBundle();
+ }
- @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
- private void showNfcPrefs() {
- Intent intentSettings = new Intent(
- Settings.ACTION_NFCSHARING_SETTINGS);
- startActivity(intentSettings);
+ qrCodeIntent.setData(mDataUri);
+ ActivityCompat.startActivity(getActivity(), qrCodeIntent, opts);
}
@Override
@@ -361,19 +336,19 @@ public class ViewKeyShareFragment extends LoaderFragment implements
protected void onPostExecute(Bitmap qrCode) {
// only change view, if fragment is attached to activity
- if (ViewKeyShareFragment.this.isAdded()) {
+ if (ViewKeyAdvShareFragment.this.isAdded()) {
// scale the image up to our actual size. we do this in code rather
// than let the ImageView do this because we don't require filtering.
Bitmap scaled = Bitmap.createScaledBitmap(qrCode,
- mFingerprintQrCode.getHeight(), mFingerprintQrCode.getHeight(),
+ mQrCode.getHeight(), mQrCode.getHeight(),
false);
- mFingerprintQrCode.setImageBitmap(scaled);
+ mQrCode.setImageBitmap(scaled);
// simple fade-in animation
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(200);
- mFingerprintQrCode.startAnimation(anim);
+ mQrCode.startAnimation(anim);
}
}
};
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java
new file mode 100644
index 000000000..bd00c6780
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvSubkeysFragment.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
+import org.sufficientlysecure.keychain.util.Log;
+
+public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
+
+ public static final String ARG_DATA_URI = "data_uri";
+
+ private ListView mSubkeysList;
+ private SubkeysAdapter mSubkeysAdapter;
+
+ private Uri mDataUriSubkeys;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static ViewKeyAdvSubkeysFragment newInstance(Uri dataUri) {
+ ViewKeyAdvSubkeysFragment frag = new ViewKeyAdvSubkeysFragment();
+
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_DATA_URI, dataUri);
+
+ frag.setArguments(args);
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
+ View root = super.onCreateView(inflater, superContainer, savedInstanceState);
+ View view = inflater.inflate(R.layout.view_key_adv_subkeys_fragment, getContainer());
+
+ mSubkeysList = (ListView) view.findViewById(R.id.keys);
+
+ return root;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
+ if (dataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
+ getActivity().finish();
+ return;
+ }
+
+ loadData(dataUri);
+ }
+
+ private void loadData(Uri dataUri) {
+ mDataUriSubkeys = KeychainContract.Keys.buildKeysUri(dataUri);
+
+ // Create an empty adapter we will use to display the loaded data.
+ mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
+ mSubkeysList.setAdapter(mSubkeysAdapter);
+
+ // Prepare the loaders. Either re-connect with an existing ones,
+ // or start new ones.
+ getLoaderManager().initLoader(0, null, this);
+ }
+
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ setContentShown(false);
+
+ return new CursorLoader(getActivity(), mDataUriSubkeys,
+ SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null);
+ }
+
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ // Avoid NullPointerExceptions, if we get an empty result set.
+ if (data.getCount() == 0) {
+ return;
+ }
+
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ mSubkeysAdapter.swapCursor(data);
+
+ // TODO: maybe show not before both are loaded!
+ setContentShown(true);
+ }
+
+ /**
+ * This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
+ * We need to make sure we are no longer using it.
+ */
+ public void onLoaderReset(Loader<Cursor> loader) {
+ mSubkeysAdapter.swapCursor(null);
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
new file mode 100644
index 000000000..c4e6639a8
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
+import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
+import org.sufficientlysecure.keychain.util.Log;
+
+public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
+
+ public static final String ARG_DATA_URI = "uri";
+
+ private ListView mUserIds;
+
+ private static final int LOADER_ID_UNIFIED = 0;
+ private static final int LOADER_ID_USER_IDS = 1;
+
+ private UserIdsAdapter mUserIdsAdapter;
+
+ private Uri mDataUri;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
+ View root = super.onCreateView(inflater, superContainer, savedInstanceState);
+ View view = inflater.inflate(R.layout.view_key_adv_main_fragment, getContainer());
+
+ mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
+
+ mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ showUserIdInfo(position);
+ }
+ });
+
+ return root;
+ }
+
+ private void showUserIdInfo(final int position) {
+ final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position);
+ final int isVerified = mUserIdsAdapter.getIsVerified(position);
+
+ DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
+ public void run() {
+ UserIdInfoDialogFragment dialogFragment =
+ UserIdInfoDialogFragment.newInstance(isRevoked, isVerified);
+
+ dialogFragment.show(getActivity().getSupportFragmentManager(), "userIdInfoDialog");
+ }
+ });
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
+ if (dataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
+ getActivity().finish();
+ return;
+ }
+
+ loadData(dataUri);
+ }
+
+ private void loadData(Uri dataUri) {
+ mDataUri = dataUri;
+
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+
+ mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
+ mUserIds.setAdapter(mUserIdsAdapter);
+
+ // Prepare the loaders. Either re-connect with an existing ones,
+ // or start new ones.
+ getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
+ getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
+ }
+
+ static final String[] UNIFIED_PROJECTION = new String[]{
+ KeyRings._ID, KeyRings.MASTER_KEY_ID,
+ KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.EXPIRY, KeyRings.HAS_ENCRYPT
+ };
+ static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
+ static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
+ static final int INDEX_UNIFIED_IS_REVOKED = 3;
+ static final int INDEX_UNIFIED_EXPIRY = 4;
+ static final int INDEX_UNIFIED_HAS_ENCRYPT = 5;
+
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ setContentShown(false);
+
+ switch (id) {
+ case LOADER_ID_UNIFIED: {
+ Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
+ return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
+ }
+ case LOADER_ID_USER_IDS: {
+ Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
+ return new CursorLoader(getActivity(), baseUri,
+ UserIdsAdapter.USER_IDS_PROJECTION, null, null, null);
+ }
+
+ default:
+ return null;
+ }
+ }
+
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ /* TODO better error handling? May cause problems when a key is deleted,
+ * because the notification triggers faster than the activity closes.
+ */
+ // Avoid NullPointerExceptions...
+ if (data.getCount() == 0) {
+ return;
+ }
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ switch (loader.getId()) {
+ case LOADER_ID_UNIFIED: {
+ if (data.moveToFirst()) {
+
+
+ break;
+ }
+ }
+
+ case LOADER_ID_USER_IDS: {
+ mUserIdsAdapter.swapCursor(data);
+ break;
+ }
+
+ }
+ setContentShown(true);
+ }
+
+ /**
+ * This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
+ * We need to make sure we are no longer using it.
+ */
+ public void onLoaderReset(Loader<Cursor> loader) {
+ switch (loader.getId()) {
+ case LOADER_ID_USER_IDS:
+ mUserIdsAdapter.swapCursor(null);
+ break;
+ }
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
new file mode 100644
index 000000000..453bfd499
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
+import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.util.Date;
+
+public class ViewKeyFragment extends LoaderFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
+
+ public static final String ARG_DATA_URI = "uri";
+
+ private ListView mUserIds;
+
+ boolean mIsSecret = false;
+
+ private static final int LOADER_ID_UNIFIED = 0;
+ private static final int LOADER_ID_USER_IDS = 1;
+
+ private UserIdsAdapter mUserIdsAdapter;
+
+ private Uri mDataUri;
+
+ ProviderHelper mProviderHelper;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static ViewKeyFragment newInstance(Uri dataUri) {
+ ViewKeyFragment frag = new ViewKeyFragment();
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_DATA_URI, dataUri);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
+ View root = super.onCreateView(inflater, superContainer, savedInstanceState);
+ View view = inflater.inflate(R.layout.view_key_fragment, getContainer());
+
+ mProviderHelper = new ProviderHelper(getActivity());
+
+ mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
+
+ mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ showUserIdInfo(position);
+ }
+ });
+
+ return root;
+ }
+
+ private void showUserIdInfo(final int position) {
+ if (!mIsSecret) {
+ final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position);
+ final int isVerified = mUserIdsAdapter.getIsVerified(position);
+
+ DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
+ public void run() {
+ UserIdInfoDialogFragment dialogFragment =
+ UserIdInfoDialogFragment.newInstance(isRevoked, isVerified);
+
+ dialogFragment.show(getActivity().getSupportFragmentManager(), "userIdInfoDialog");
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
+ if (dataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
+ getActivity().finish();
+ return;
+ }
+
+ loadData(dataUri);
+ }
+
+
+ // 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.EXPIRY,
+ KeychainContract.KeyRings.VERIFIED,
+ KeychainContract.KeyRings.HAS_ANY_SECRET,
+ KeychainContract.KeyRings.FINGERPRINT,
+ KeychainContract.KeyRings.HAS_ENCRYPT
+ };
+
+ 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_EXPIRY = 4;
+ static final int INDEX_VERIFIED = 5;
+ static final int INDEX_HAS_ANY_SECRET = 6;
+ static final int INDEX_FINGERPRINT = 7;
+ static final int INDEX_HAS_ENCRYPT = 8;
+
+ private void loadData(Uri dataUri) {
+ mDataUri = dataUri;
+
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+
+ // Prepare the loaders. Either re-connect with an existing ones,
+ // or start new ones.
+ getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
+ }
+
+ // don't show revoked user ids here, irrelevant for average users
+ public static final String USER_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
+
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ setContentShown(false);
+
+ switch (id) {
+ case LOADER_ID_UNIFIED: {
+ Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
+ return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
+ }
+ case LOADER_ID_USER_IDS: {
+ Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
+ return new CursorLoader(getActivity(), baseUri,
+ UserIdsAdapter.USER_IDS_PROJECTION, USER_IDS_WHERE, null, null);
+ }
+
+ default:
+ return null;
+ }
+ }
+
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ /* TODO better error handling? May cause problems when a key is deleted,
+ * because the notification triggers faster than the activity closes.
+ */
+ // Avoid NullPointerExceptions...
+ if (data.getCount() == 0) {
+ return;
+ }
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ switch (loader.getId()) {
+ case LOADER_ID_UNIFIED: {
+ if (data.moveToFirst()) {
+
+ mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
+ boolean hasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
+ boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
+ boolean isExpired = !data.isNull(INDEX_EXPIRY)
+ && new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
+ boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
+
+ // load user ids after we know if it's a secret key
+ mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, false, !mIsSecret, null);
+ mUserIds.setAdapter(mUserIdsAdapter);
+ getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
+
+ break;
+ }
+ }
+
+ case LOADER_ID_USER_IDS: {
+ mUserIdsAdapter.swapCursor(data);
+ break;
+ }
+
+ }
+ setContentShown(true);
+ }
+
+ /**
+ * This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
+ * We need to make sure we are no longer using it.
+ */
+ public void onLoaderReset(Loader<Cursor> loader) {
+ switch (loader.getId()) {
+ case LOADER_ID_USER_IDS: {
+ mUserIdsAdapter.swapCursor(null);
+ break;
+ }
+ }
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
deleted file mode 100644
index 8101006e1..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.PorterDuff;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.CursorLoader;
-import android.support.v4.content.Loader;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ImageView;
-import android.widget.ListView;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
-import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
-import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
-import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
-import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
-import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-
-import java.util.Date;
-
-public class ViewKeyMainFragment extends LoaderFragment implements
- LoaderManager.LoaderCallbacks<Cursor> {
-
- public static final String ARG_DATA_URI = "uri";
-
- private View mActionLink, mActionLinkDivider;
- private View mActionEdit;
- private View mActionEditDivider;
- private View mActionEncryptFiles;
- private View mActionEncryptText;
- private View mActionEncryptTextText;
- private View mActionCertify;
- private View mActionCertifyText;
- private ImageView mActionCertifyImage;
- private View mActionUpdate;
-
- private ListView mUserIds;
-
- private static final int LOADER_ID_UNIFIED = 0;
- private static final int LOADER_ID_USER_IDS = 1;
-
- // conservative attitude
- private boolean mHasEncrypt = true;
-
- private UserIdsAdapter mUserIdsAdapter;
-
- private Uri mDataUri;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
- View root = super.onCreateView(inflater, superContainer, savedInstanceState);
- View view = inflater.inflate(R.layout.view_key_main_fragment, getContainer());
-
- mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
- mActionLink = view.findViewById(R.id.view_key_action_link);
- mActionLinkDivider = view.findViewById(R.id.view_key_action_link);
- mActionEdit = view.findViewById(R.id.view_key_action_edit);
- mActionEditDivider = view.findViewById(R.id.view_key_action_edit_divider);
- mActionEncryptText = view.findViewById(R.id.view_key_action_encrypt_text);
- mActionEncryptTextText = view.findViewById(R.id.view_key_action_encrypt_text_text);
- mActionEncryptFiles = view.findViewById(R.id.view_key_action_encrypt_files);
- mActionCertify = view.findViewById(R.id.view_key_action_certify);
- mActionCertifyText = view.findViewById(R.id.view_key_action_certify_text);
- mActionCertifyImage = (ImageView) view.findViewById(R.id.view_key_action_certify_image);
- // make certify image gray, like action icons
- mActionCertifyImage.setColorFilter(getResources().getColor(R.color.tertiary_text_light),
- PorterDuff.Mode.SRC_IN);
- mActionUpdate = view.findViewById(R.id.view_key_action_update);
-
- mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- showUserIdInfo(position);
- }
- });
-
- return root;
- }
-
- private void showUserIdInfo(final int position) {
- final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position);
- final int isVerified = mUserIdsAdapter.getIsVerified(position);
-
- DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
- public void run() {
- UserIdInfoDialogFragment dialogFragment =
- UserIdInfoDialogFragment.newInstance(isRevoked, isVerified);
-
- dialogFragment.show(getActivity().getSupportFragmentManager(), "userIdInfoDialog");
- }
- });
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
- if (dataUri == null) {
- Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
- getActivity().finish();
- return;
- }
-
- loadData(dataUri);
- }
-
- private void loadData(Uri dataUri) {
- mDataUri = dataUri;
-
- Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
-
- mActionEncryptFiles.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- encrypt(mDataUri, false);
- }
- });
- mActionEncryptText.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- encrypt(mDataUri, true);
- }
- });
- mActionCertify.setOnClickListener(new View.OnClickListener() {
- public void onClick(View view) {
- certify(mDataUri);
- }
- });
- mActionLink.setOnClickListener(new View.OnClickListener() {
- public void onClick(View view) {
- linkKey(mDataUri);
- }
- });
- mActionEdit.setOnClickListener(new View.OnClickListener() {
- public void onClick(View view) {
- editKey(mDataUri);
- }
- });
- mActionUpdate.setOnClickListener(new View.OnClickListener() {
- public void onClick(View view) {
- try {
- updateFromKeyserver(mDataUri, new ProviderHelper(getActivity()));
- } catch (NotFoundException e) {
- Notify.showNotify(getActivity(), R.string.error_key_not_found, Notify.Style.ERROR);
- }
- }
- });
-
- mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
- mUserIds.setAdapter(mUserIdsAdapter);
-
- // Prepare the loaders. Either re-connect with an existing ones,
- // or start new ones.
- getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
- getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
- }
-
- static final String[] UNIFIED_PROJECTION = new String[]{
- KeyRings._ID, KeyRings.MASTER_KEY_ID,
- KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.EXPIRY, KeyRings.HAS_ENCRYPT
- };
- static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
- static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
- static final int INDEX_UNIFIED_IS_REVOKED = 3;
- static final int INDEX_UNIFIED_EXPIRY = 4;
- static final int INDEX_UNIFIED_HAS_ENCRYPT = 5;
-
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- setContentShown(false);
-
- switch (id) {
- case LOADER_ID_UNIFIED: {
- Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
- return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
- }
- case LOADER_ID_USER_IDS: {
- Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
- return new CursorLoader(getActivity(), baseUri,
- UserIdsAdapter.USER_IDS_PROJECTION, null, null, null);
- }
-
- default:
- return null;
- }
- }
-
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- /* TODO better error handling? May cause problems when a key is deleted,
- * because the notification triggers faster than the activity closes.
- */
- // Avoid NullPointerExceptions...
- if (data.getCount() == 0) {
- return;
- }
- // Swap the new cursor in. (The framework will take care of closing the
- // old cursor once we return.)
- switch (loader.getId()) {
- case LOADER_ID_UNIFIED: {
- if (data.moveToFirst()) {
- if (data.getInt(INDEX_UNIFIED_HAS_ANY_SECRET) != 0) {
- // edit button
- mActionLink.setVisibility(View.VISIBLE);
- mActionLinkDivider.setVisibility(View.VISIBLE);
- mActionEdit.setVisibility(View.VISIBLE);
- mActionEditDivider.setVisibility(View.VISIBLE);
- } else {
- // edit button
- mActionLink.setVisibility(View.GONE);
- mActionLinkDivider.setVisibility(View.GONE);
- mActionEdit.setVisibility(View.GONE);
- mActionEditDivider.setVisibility(View.GONE);
- }
-
- // If this key is revoked, it cannot be used for anything!
- if (data.getInt(INDEX_UNIFIED_IS_REVOKED) != 0) {
- mActionEdit.setEnabled(false);
- mActionCertify.setEnabled(false);
- mActionCertifyText.setEnabled(false);
- mActionEncryptText.setEnabled(false);
- mActionEncryptTextText.setEnabled(false);
- mActionEncryptFiles.setEnabled(false);
- } else {
- mActionEdit.setEnabled(true);
-
- Date expiryDate = new Date(data.getLong(INDEX_UNIFIED_EXPIRY) * 1000);
- if (!data.isNull(INDEX_UNIFIED_EXPIRY) && expiryDate.before(new Date())) {
- mActionCertify.setEnabled(false);
- mActionCertifyText.setEnabled(false);
- mActionEncryptText.setEnabled(false);
- mActionEncryptTextText.setEnabled(false);
- mActionEncryptFiles.setEnabled(false);
- } else {
- mActionCertify.setEnabled(true);
- mActionCertifyText.setEnabled(true);
- mActionEncryptText.setEnabled(true);
- mActionEncryptTextText.setEnabled(true);
- mActionEncryptFiles.setEnabled(true);
- }
- }
-
- mHasEncrypt = data.getInt(INDEX_UNIFIED_HAS_ENCRYPT) != 0;
-
- break;
- }
- }
-
- case LOADER_ID_USER_IDS:
- mUserIdsAdapter.swapCursor(data);
- break;
-
- }
- setContentShown(true);
- }
-
- /**
- * This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
- * We need to make sure we are no longer using it.
- */
- public void onLoaderReset(Loader<Cursor> loader) {
- switch (loader.getId()) {
- case LOADER_ID_USER_IDS:
- mUserIdsAdapter.swapCursor(null);
- break;
- }
- }
-
- private void encrypt(Uri dataUri, boolean text) {
- // If there is no encryption key, don't bother.
- if (!mHasEncrypt) {
- Notify.showNotify(getActivity(), R.string.error_no_encrypt_subkey, Notify.Style.ERROR);
- return;
- }
- try {
- long keyId = new ProviderHelper(getActivity())
- .getCachedPublicKeyRing(dataUri)
- .extractOrGetMasterKeyId();
- long[] encryptionKeyIds = new long[]{keyId};
- Intent intent;
- if (text) {
- intent = new Intent(getActivity(), EncryptTextActivity.class);
- intent.setAction(EncryptTextActivity.ACTION_ENCRYPT_TEXT);
- intent.putExtra(EncryptTextActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
- } else {
- intent = new Intent(getActivity(), EncryptFilesActivity.class);
- intent.setAction(EncryptFilesActivity.ACTION_ENCRYPT_DATA);
- intent.putExtra(EncryptFilesActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
- }
- // used instead of startActivity set actionbar based on callingPackage
- startActivityForResult(intent, 0);
- } catch (PgpKeyNotFoundException e) {
- Log.e(Constants.TAG, "key not found!", e);
- }
- }
-
- private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper)
- throws ProviderHelper.NotFoundException {
- byte[] blob = (byte[]) providerHelper.getGenericData(
- KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri),
- KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
- String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob);
-
- Intent queryIntent = new Intent(getActivity(), ImportKeysActivity.class);
- queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT);
- queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint);
-
- startActivityForResult(queryIntent, 0);
- }
-
- private void certify(Uri dataUri) {
- long keyId = 0;
- try {
- keyId = new ProviderHelper(getActivity())
- .getCachedPublicKeyRing(dataUri)
- .extractOrGetMasterKeyId();
- } catch (PgpKeyNotFoundException e) {
- Log.e(Constants.TAG, "key not found!", e);
- }
- Intent certifyIntent = new Intent(getActivity(), CertifyKeyActivity.class);
- certifyIntent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{keyId});
- startActivityForResult(certifyIntent, 0);
- }
-
- private void editKey(Uri dataUri) {
- Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
- editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri));
- startActivityForResult(editIntent, 0);
- }
-
- private void linkKey(Uri dataUri) {
- Intent editIntent = new Intent(getActivity(), LinkedIdWizard.class);
- editIntent.setData(KeyRings.buildUnifiedKeyRingUri(dataUri));
- startActivityForResult(editIntent, 0);
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
new file mode 100644
index 000000000..25edc7a02
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2014 Tim Bray <tbray@textuality.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.os.AsyncTask;
+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.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.text.style.StyleSpan;
+import android.text.style.URLSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TableLayout;
+import android.widget.TableRow;
+import android.widget.TextView;
+
+import com.textuality.keybase.lib.KeybaseException;
+import com.textuality.keybase.lib.Proof;
+import com.textuality.keybase.lib.User;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.List;
+
+public class ViewKeyTrustFragment extends LoaderFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
+
+ public static final String ARG_DATA_URI = "uri";
+
+ private View mStartSearch;
+ private TextView mTrustReadout;
+ private TextView mReportHeader;
+ private TableLayout mProofListing;
+ private LayoutInflater mInflater;
+ private View mProofVerifyHeader;
+ private TextView mProofVerifyDetail;
+
+ private static final int LOADER_ID_DATABASE = 1;
+
+ // for retrieving the key we’re working on
+ private Uri mDataUri;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
+ View root = super.onCreateView(inflater, superContainer, savedInstanceState);
+ View view = inflater.inflate(R.layout.view_key_adv_keybase_fragment, getContainer());
+ mInflater = inflater;
+
+ mTrustReadout = (TextView) view.findViewById(R.id.view_key_trust_readout);
+ mStartSearch = view.findViewById(R.id.view_key_trust_search_cloud);
+ mStartSearch.setEnabled(false);
+ mReportHeader = (TextView) view.findViewById(R.id.view_key_trust_cloud_narrative);
+ mProofListing = (TableLayout) view.findViewById(R.id.view_key_proof_list);
+ mProofVerifyHeader = view.findViewById(R.id.view_key_proof_verify_header);
+ mProofVerifyDetail = (TextView) view.findViewById(R.id.view_key_proof_verify_detail);
+ mReportHeader.setVisibility(View.GONE);
+ mProofListing.setVisibility(View.GONE);
+ mProofVerifyHeader.setVisibility(View.GONE);
+ mProofVerifyDetail.setVisibility(View.GONE);
+
+ return root;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
+ if (dataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
+ getActivity().finish();
+ return;
+ }
+ mDataUri = dataUri;
+
+ // retrieve the key from the database
+ getLoaderManager().initLoader(LOADER_ID_DATABASE, null, this);
+ }
+
+ static final String[] TRUST_PROJECTION = new String[]{
+ KeyRings._ID, KeyRings.FINGERPRINT, KeyRings.IS_REVOKED, KeyRings.EXPIRY,
+ KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED
+ };
+ static final int INDEX_TRUST_FINGERPRINT = 1;
+ static final int INDEX_TRUST_IS_REVOKED = 2;
+ static final int INDEX_TRUST_EXPIRY = 3;
+ static final int INDEX_UNIFIED_HAS_ANY_SECRET = 4;
+ static final int INDEX_VERIFIED = 5;
+
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ setContentShown(false);
+
+ switch (id) {
+ case LOADER_ID_DATABASE: {
+ Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
+ return new CursorLoader(getActivity(), baseUri, TRUST_PROJECTION, null, null, null);
+ }
+ // decided to just use an AsyncTask for keybase, but maybe later
+ default:
+ return null;
+ }
+ }
+
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ /* TODO better error handling? May cause problems when a key is deleted,
+ * because the notification triggers faster than the activity closes.
+ */
+ // Avoid NullPointerExceptions...
+ if (data.getCount() == 0) {
+ return;
+ }
+
+ boolean nothingSpecial = true;
+ StringBuilder message = new StringBuilder();
+
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ if (data.moveToFirst()) {
+
+ if (data.getInt(INDEX_UNIFIED_HAS_ANY_SECRET) != 0) {
+ message.append(getString(R.string.key_trust_it_is_yours)).append("\n");
+ nothingSpecial = false;
+ } else if (data.getInt(INDEX_VERIFIED) != 0) {
+ message.append(getString(R.string.key_trust_already_verified)).append("\n");
+ nothingSpecial = false;
+ }
+
+ // If this key is revoked, don’t trust it!
+ if (data.getInt(INDEX_TRUST_IS_REVOKED) != 0) {
+ message.append(getString(R.string.key_trust_revoked)).
+ append(getString(R.string.key_trust_old_keys));
+
+ nothingSpecial = false;
+ } else {
+ Date expiryDate = new Date(data.getLong(INDEX_TRUST_EXPIRY) * 1000);
+ if (!data.isNull(INDEX_TRUST_EXPIRY) && expiryDate.before(new Date())) {
+
+ // if expired, don’t trust it!
+ message.append(getString(R.string.key_trust_expired)).
+ append(getString(R.string.key_trust_old_keys));
+
+ nothingSpecial = false;
+ }
+ }
+
+ if (nothingSpecial) {
+ message.append(getString(R.string.key_trust_maybe));
+ }
+
+ final byte[] fp = data.getBlob(INDEX_TRUST_FINGERPRINT);
+ final String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fp);
+ if (fingerprint != null) {
+
+ mStartSearch.setEnabled(true);
+ mStartSearch.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mStartSearch.setEnabled(false);
+ new DescribeKey().execute(fingerprint);
+ }
+ });
+ }
+ }
+
+ mTrustReadout.setText(message);
+ setContentShown(true);
+ }
+
+ /**
+ * This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
+ * We need to make sure we are no longer using it.
+ */
+ public void onLoaderReset(Loader<Cursor> loader) {
+ // no-op in this case I think
+ }
+
+ class ResultPage {
+ String mHeader;
+ final List<CharSequence> mProofs;
+
+ public ResultPage(String header, List<CharSequence> proofs) {
+ mHeader = header;
+ mProofs = proofs;
+ }
+ }
+
+ // look for evidence from keybase in the background, make tabular version of result
+ //
+ private class DescribeKey extends AsyncTask<String, Void, ResultPage> {
+
+ @Override
+ protected ResultPage doInBackground(String... args) {
+ String fingerprint = args[0];
+
+ final ArrayList<CharSequence> proofList = new ArrayList<CharSequence>();
+ final Hashtable<Integer, ArrayList<Proof>> proofs = new Hashtable<Integer, ArrayList<Proof>>();
+ try {
+ User keybaseUser = User.findByFingerprint(fingerprint);
+ for (Proof proof : keybaseUser.getProofs()) {
+ Integer proofType = proof.getType();
+ appendIfOK(proofs, proofType, proof);
+ }
+
+ // a one-liner in a modern programming language
+ for (Integer proofType : proofs.keySet()) {
+ Proof[] x = {};
+ Proof[] proofsFor = proofs.get(proofType).toArray(x);
+ if (proofsFor.length > 0) {
+ SpannableStringBuilder ssb = new SpannableStringBuilder();
+ ssb.append(getProofNarrative(proofType)).append(" ");
+
+ int i = 0;
+ while (i < proofsFor.length - 1) {
+ appendProofLinks(ssb, fingerprint, proofsFor[i]);
+ ssb.append(", ");
+ i++;
+ }
+ appendProofLinks(ssb, fingerprint, proofsFor[i]);
+ proofList.add(ssb);
+ }
+ }
+
+ } catch (KeybaseException ignored) {
+ }
+
+ return new ResultPage(getString(R.string.key_trust_results_prefix), proofList);
+ }
+
+ private SpannableStringBuilder appendProofLinks(SpannableStringBuilder ssb, final String fingerprint, final Proof proof) throws KeybaseException {
+ int startAt = ssb.length();
+ String handle = proof.getHandle();
+ ssb.append(handle);
+ ssb.setSpan(new URLSpan(proof.getServiceUrl()), startAt, startAt + handle.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ if (haveProofFor(proof.getType())) {
+ ssb.append("\u00a0[");
+ startAt = ssb.length();
+ String verify = getString(R.string.keybase_verify);
+ ssb.append(verify);
+ ClickableSpan clicker = new ClickableSpan() {
+ @Override
+ public void onClick(View view) {
+ verify(proof, fingerprint);
+ }
+ };
+ ssb.setSpan(clicker, startAt, startAt + verify.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append("]");
+ }
+ return ssb;
+ }
+
+ @Override
+ protected void onPostExecute(ResultPage result) {
+ super.onPostExecute(result);
+ if (result.mProofs.isEmpty()) {
+ result.mHeader = getActivity().getString(R.string.key_trust_no_cloud_evidence);
+ }
+
+ mStartSearch.setVisibility(View.GONE);
+ mReportHeader.setVisibility(View.VISIBLE);
+ mProofListing.setVisibility(View.VISIBLE);
+ mReportHeader.setText(result.mHeader);
+
+ int rowNumber = 1;
+ for (CharSequence s : result.mProofs) {
+ TableRow row = (TableRow) mInflater.inflate(R.layout.view_key_adv_keybase_proof, null);
+ TextView number = (TextView) row.findViewById(R.id.proof_number);
+ TextView text = (TextView) row.findViewById(R.id.proof_text);
+ number.setText(Integer.toString(rowNumber++) + ". ");
+ text.setText(s);
+ text.setMovementMethod(LinkMovementMethod.getInstance());
+ mProofListing.addView(row);
+ }
+
+ // mSearchReport.loadDataWithBaseURL("file:///android_res/drawable/", s, "text/html", "UTF-8", null);
+ }
+ }
+
+ private String getProofNarrative(int proofType) {
+ int stringIndex;
+ switch (proofType) {
+ case Proof.PROOF_TYPE_TWITTER: stringIndex = R.string.keybase_narrative_twitter; break;
+ case Proof.PROOF_TYPE_GITHUB: stringIndex = R.string.keybase_narrative_github; break;
+ case Proof.PROOF_TYPE_DNS: stringIndex = R.string.keybase_narrative_dns; break;
+ case Proof.PROOF_TYPE_WEB_SITE: stringIndex = R.string.keybase_narrative_web_site; break;
+ case Proof.PROOF_TYPE_HACKERNEWS: stringIndex = R.string.keybase_narrative_hackernews; break;
+ case Proof.PROOF_TYPE_COINBASE: stringIndex = R.string.keybase_narrative_coinbase; break;
+ case Proof.PROOF_TYPE_REDDIT: stringIndex = R.string.keybase_narrative_reddit; break;
+ default: stringIndex = R.string.keybase_narrative_unknown;
+ }
+ return getActivity().getString(stringIndex);
+ }
+
+ private void appendIfOK(Hashtable<Integer, ArrayList<Proof>> table, Integer proofType, Proof proof) throws KeybaseException {
+ ArrayList<Proof> list = table.get(proofType);
+ if (list == null) {
+ list = new ArrayList<Proof>();
+ table.put(proofType, list);
+ }
+ list.add(proof);
+ }
+
+ // which proofs do we have working verifiers for?
+ private boolean haveProofFor(int proofType) {
+ switch (proofType) {
+ case Proof.PROOF_TYPE_TWITTER: return true;
+ case Proof.PROOF_TYPE_GITHUB: return true;
+ case Proof.PROOF_TYPE_DNS: return true;
+ case Proof.PROOF_TYPE_WEB_SITE: return true;
+ case Proof.PROOF_TYPE_HACKERNEWS: return true;
+ case Proof.PROOF_TYPE_COINBASE: return true;
+ case Proof.PROOF_TYPE_REDDIT: return true;
+ default: return false;
+ }
+ }
+
+ private void verify(final Proof proof, final String fingerprint) {
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+ Bundle data = new Bundle();
+ intent.setAction(KeychainIntentService.ACTION_VERIFY_KEYBASE_PROOF);
+
+ data.putString(KeychainIntentService.KEYBASE_PROOF, proof.toString());
+ data.putString(KeychainIntentService.KEYBASE_REQUIRED_FINGERPRINT, fingerprint);
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ mProofVerifyDetail.setVisibility(View.GONE);
+
+ // Create a new Messenger for the communication back after proof work is done
+ //
+ KeychainIntentServiceHandler handler = new KeychainIntentServiceHandler(getActivity(),
+ getString(R.string.progress_verifying_signature), ProgressDialog.STYLE_HORIZONTAL) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ Bundle returnData = message.getData();
+ String msg = returnData.getString(KeychainIntentServiceHandler.DATA_MESSAGE);
+ SpannableStringBuilder ssb = new SpannableStringBuilder();
+
+ if ((msg != null) && msg.equals("OK")) {
+
+ //yay
+ String proofUrl = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PROOF_URL);
+ String presenceUrl = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_URL);
+ String presenceLabel = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_LABEL);
+
+ String proofLabel;
+ switch (proof.getType()) {
+ case Proof.PROOF_TYPE_TWITTER:
+ proofLabel = getString(R.string.keybase_twitter_proof);
+ break;
+ case Proof.PROOF_TYPE_DNS:
+ proofLabel = getString(R.string.keybase_dns_proof);
+ break;
+ case Proof.PROOF_TYPE_WEB_SITE:
+ proofLabel = getString(R.string.keybase_web_site_proof);
+ break;
+ case Proof.PROOF_TYPE_GITHUB:
+ proofLabel = getString(R.string.keybase_github_proof);
+ break;
+ case Proof.PROOF_TYPE_REDDIT:
+ proofLabel = getString(R.string.keybase_reddit_proof);
+ break;
+ default:
+ proofLabel = getString(R.string.keybase_a_post);
+ break;
+ }
+
+ ssb.append(getString(R.string.keybase_proof_succeeded));
+ StyleSpan bold = new StyleSpan(Typeface.BOLD);
+ ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append("\n\n");
+ int length = ssb.length();
+ ssb.append(proofLabel);
+ if (proofUrl != null) {
+ URLSpan postLink = new URLSpan(proofUrl);
+ ssb.setSpan(postLink, length, length + proofLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ if (Proof.PROOF_TYPE_DNS == proof.getType()) {
+ ssb.append(" ").append(getString(R.string.keybase_for_the_domain)).append(" ");
+ } else {
+ ssb.append(" ").append(getString(R.string.keybase_fetched_from)).append(" ");
+ }
+ length = ssb.length();
+ URLSpan presenceLink = new URLSpan(presenceUrl);
+ ssb.append(presenceLabel);
+ ssb.setSpan(presenceLink, length, length + presenceLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ if (Proof.PROOF_TYPE_REDDIT == proof.getType()) {
+ ssb.append(", ").
+ append(getString(R.string.keybase_reddit_attribution)).
+ append(" “").append(proof.getHandle()).append("”, ");
+ }
+ ssb.append(" ").append(getString(R.string.keybase_contained_signature));
+ } else {
+ // verification failed!
+ msg = returnData.getString(KeychainIntentServiceHandler.DATA_ERROR);
+ ssb.append(getString(R.string.keybase_proof_failure));
+ if (msg == null) {
+ msg = getString(R.string.keybase_unknown_proof_failure);
+ }
+ StyleSpan bold = new StyleSpan(Typeface.BOLD);
+ ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append("\n\n").append(msg);
+ }
+ mProofVerifyHeader.setVisibility(View.VISIBLE);
+ mProofVerifyDetail.setVisibility(View.VISIBLE);
+ mProofVerifyDetail.setMovementMethod(LinkMovementMethod.getInstance());
+ mProofVerifyDetail.setText(ssb);
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(handler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ handler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
index 6c81e9193..6ba9e26ad 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
@@ -95,8 +95,8 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
* @see org.sufficientlysecure.keychain.operations.ImportExportOperation
*/
public ArrayList<ImportKeysListEntry> getSelectedEntries() {
- ArrayList<ImportKeysListEntry> result = new ArrayList<ImportKeysListEntry>();
- ArrayList<ImportKeysListEntry> secrets = new ArrayList<ImportKeysListEntry>();
+ ArrayList<ImportKeysListEntry> result = new ArrayList<>();
+ ArrayList<ImportKeysListEntry> secrets = new ArrayList<>();
if (mData == null) {
return result;
}
@@ -175,9 +175,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
}
if (entry.isRevoked()) {
- KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_REVOKED, true);
+ KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
} else if (entry.isExpired()) {
- KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_EXPIRED, true);
+ KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
}
if (entry.isRevoked() || entry.isExpired()) {
@@ -213,8 +213,24 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
// destroyLoader view from holder
holder.userIdsList.removeAllViews();
+ // we want conventional gpg UserIDs first, then Keybase ”proofs”
HashMap<String, HashSet<String>> mergedUserIds = entry.getMergedUserIds();
- for (Map.Entry<String, HashSet<String>> pair : mergedUserIds.entrySet()) {
+ ArrayList<Map.Entry<String, HashSet<String>>> sortedIds = new ArrayList<Map.Entry<String, HashSet<String>>>(mergedUserIds.entrySet());
+ java.util.Collections.sort(sortedIds, new java.util.Comparator<Map.Entry<String, HashSet<String>>>() {
+ @Override
+ public int compare(Map.Entry<String, HashSet<String>> entry1, Map.Entry<String, HashSet<String>> entry2) {
+
+ // sort keybase UserIds after non-Keybase
+ boolean e1IsKeybase = entry1.getKey().contains(":");
+ boolean e2IsKeybase = entry2.getKey().contains(":");
+ if (e1IsKeybase != e2IsKeybase) {
+ return (e1IsKeybase) ? 1 : -1;
+ }
+ return entry1.getKey().compareTo(entry2.getKey());
+ }
+ });
+
+ for (Map.Entry<String, HashSet<String>> pair : sortedIds) {
String cUserId = pair.getKey();
HashSet<String> cEmails = pair.getValue();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
index 176c3ff5b..4781864dd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
@@ -21,13 +21,13 @@ import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.keyimport.CloudSearch;
+import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.Keyserver;
import org.sufficientlysecure.keychain.operations.results.GetKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.util.Preferences;
-import org.sufficientlysecure.keychain.keyimport.CloudSearch;
-import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -39,7 +39,7 @@ public class ImportKeysListCloudLoader
Preferences.CloudSearchPrefs mCloudPrefs;
String mServerQuery;
- private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<ImportKeysListEntry>();
+ private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<>();
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs) {
@@ -51,7 +51,7 @@ public class ImportKeysListCloudLoader
@Override
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, null);
if (mServerQuery == null) {
Log.e(Constants.TAG, "mServerQuery is null!");
@@ -119,7 +119,7 @@ public class ImportKeysListCloudLoader
mEntryList.addAll(searchResult);
}
GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_OK, null);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, getKeyResult);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, getKeyResult);
} catch (Keyserver.CloudSearchFailureException e) {
// convert exception to result parcel
int error = GetKeyResult.RESULT_ERROR;
@@ -140,7 +140,7 @@ public class ImportKeysListCloudLoader
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(logType, 0);
GetKeyResult getKeyResult = new GetKeyResult(error, log);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, getKeyResult);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, getKeyResult);
}
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
index cecad2716..5447c5f96 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
@@ -24,9 +24,9 @@ import android.support.v4.util.LongSparseArray;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.operations.results.GetKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
@@ -35,28 +35,15 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Iterator;
public class ImportKeysListLoader
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
- public static class NonPgpPartException extends Exception {
- private int mCount;
-
- public NonPgpPartException(int count) {
- this.mCount = count;
- }
-
- public int getCount() {
- return mCount;
- }
- }
-
final Context mContext;
final InputData mInputData;
- ArrayList<ImportKeysListEntry> mData = new ArrayList<ImportKeysListEntry>();
- LongSparseArray<ParcelableKeyRing> mParcelableRings = new LongSparseArray<ParcelableKeyRing>();
+ ArrayList<ImportKeysListEntry> mData = new ArrayList<>();
+ LongSparseArray<ParcelableKeyRing> mParcelableRings = new LongSparseArray<>();
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
public ImportKeysListLoader(Context context, InputData inputData) {
@@ -73,7 +60,7 @@ public class ImportKeysListLoader
}
GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_OK, null);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mData, getKeyResult);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mData, getKeyResult);
if (mInputData == null) {
Log.e(Constants.TAG, "Input data is null!");
@@ -140,7 +127,7 @@ public class ImportKeysListLoader
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(OperationResult.LogType.MSG_GET_NO_VALID_KEYS, 0);
GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_ERROR_NO_VALID_KEYS, log);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
+ mEntryListWrapper = new AsyncTaskResultWrapper<>
(mData, getKeyResult);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
index 80d605fb9..b8fe21941 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
@@ -33,7 +33,7 @@ public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
static <K, V extends Comparable<? super V>> SortedSet<Map.Entry<K, V>> entriesSortedByValues(
Map<K, V> map) {
- SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<Map.Entry<K, V>>(
+ SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<>(
new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
index 9f29826ef..015775669 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
@@ -21,13 +21,13 @@ import android.content.Context;
import android.database.Cursor;
import android.os.Parcel;
import android.support.v4.util.LongSparseArray;
+import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
-import android.support.v4.widget.CursorAdapter;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
@@ -44,7 +44,7 @@ public class MultiUserIdsAdapter extends CursorAdapter {
public MultiUserIdsAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
- mCheckStates = new ArrayList<Boolean>();
+ mCheckStates = new ArrayList<>();
}
@Override
@@ -148,7 +148,7 @@ public class MultiUserIdsAdapter extends CursorAdapter {
}
public ArrayList<CertifyAction> getSelectedCertifyActions() {
- LongSparseArray<CertifyAction> actions = new LongSparseArray<CertifyAction>();
+ LongSparseArray<CertifyAction> actions = new LongSparseArray<>();
for (int i = 0; i < mCheckStates.size(); i++) {
if (mCheckStates.get(i)) {
mCursor.moveToPosition(i);
@@ -171,7 +171,7 @@ public class MultiUserIdsAdapter extends CursorAdapter {
}
}
- ArrayList<CertifyAction> result = new ArrayList<CertifyAction>(actions.size());
+ ArrayList<CertifyAction> result = new ArrayList<>(actions.size());
for (int i = 0; i < actions.size(); i++) {
result.add(actions.valueAt(i));
}
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 330254a8f..963e77fe9 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
@@ -27,7 +27,7 @@ import java.util.ArrayList;
public class PagerTabStripAdapter extends FragmentPagerAdapter {
protected final Activity mActivity;
- protected final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+ protected final ArrayList<TabInfo> mTabs = new ArrayList<>();
static final class TabInfo {
public final Class<?> clss;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
index 60c130969..a836b35df 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
@@ -30,9 +30,9 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
/**
@@ -133,11 +133,11 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter {
boolean enabled;
if (cursor.getInt(mIndexIsRevoked) != 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_REVOKED, true);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
enabled = false;
} else if (cursor.getInt(mIndexIsExpiry) != 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_EXPIRED, true);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
enabled = false;
} else {
h.statusIcon.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
index a032e96fc..ff5fbb49a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
@@ -35,11 +35,11 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.util.Calendar;
import java.util.Date;
@@ -160,7 +160,11 @@ public class SubkeysAdapter extends CursorAdapter {
cursor.getString(INDEX_KEY_CURVE_OID)
));
- if (mSaveKeyringParcel != null && mSaveKeyringParcel.mStripSubKeys.contains(keyId)) {
+ SubkeyChange change = mSaveKeyringParcel != null
+ ? mSaveKeyringParcel.getSubkeyChange(keyId)
+ : null;
+
+ if (change != null && change.mDummyStrip) {
algorithmStr.append(", ");
final SpannableString boldStripped = new SpannableString(
context.getString(R.string.key_stripped)
@@ -268,12 +272,12 @@ public class SubkeysAdapter extends CursorAdapter {
PorterDuff.Mode.SRC_IN);
if (isRevoked) {
- vStatus.setImageResource(R.drawable.status_signature_revoked_cutout);
+ vStatus.setImageResource(R.drawable.status_signature_revoked_cutout_24px);
vStatus.setColorFilter(
mContext.getResources().getColor(R.color.bg_gray),
PorterDuff.Mode.SRC_IN);
} else if (isExpired) {
- vStatus.setImageResource(R.drawable.status_signature_expired_cutout);
+ vStatus.setImageResource(R.drawable.status_signature_expired_cutout_24px);
vStatus.setColorFilter(
mContext.getResources().getColor(R.color.bg_gray),
PorterDuff.Mode.SRC_IN);
@@ -297,7 +301,7 @@ public class SubkeysAdapter extends CursorAdapter {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
- View view = mInflater.inflate(R.layout.view_key_subkey_item, null);
+ View view = mInflater.inflate(R.layout.view_key_adv_subkey_item, null);
if (mDefaultTextColor == null) {
TextView keyId = (TextView) view.findViewById(R.id.subkey_item_key_id);
mDefaultTextColor = keyId.getTextColors();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java
index 9f5d5341e..d2359a387 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java
@@ -31,8 +31,8 @@ import android.widget.TextView;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.util.Calendar;
import java.util.Date;
@@ -68,7 +68,7 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// Not recycled, inflate a new view
- convertView = mInflater.inflate(R.layout.view_key_subkey_item, null);
+ convertView = mInflater.inflate(R.layout.view_key_adv_subkey_item, null);
final ViewHolder holder = new ViewHolder();
holder.vKeyId = (TextView) convertView.findViewById(R.id.subkey_item_key_id);
holder.vKeyDetails = (TextView) convertView.findViewById(R.id.subkey_item_details);
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 9ddfa90be..44afed351 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
@@ -33,7 +33,7 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
- private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+ private final ArrayList<TabInfo> mTabs = new ArrayList<>();
static final class TabInfo {
public final Class<?> clss;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
index 7b8670f22..73c42b1be 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
@@ -34,6 +34,9 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
@@ -43,6 +46,7 @@ public class UserAttributesAdapter extends CursorAdapter implements AdapterView.
private LayoutInflater mInflater;
private final ArrayList<Boolean> mCheckStates;
private SaveKeyringParcel mSaveKeyringParcel;
+ private boolean mShowStatusImages;
public static final String[] USER_PACKETS_PROJECTION = new String[]{
UserPackets._ID,
@@ -64,12 +68,13 @@ public class UserAttributesAdapter extends CursorAdapter implements AdapterView.
private static final int INDEX_IS_REVOKED = 7;
public UserAttributesAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes,
- SaveKeyringParcel saveKeyringParcel) {
+ boolean showStatusImages, SaveKeyringParcel saveKeyringParcel) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
mCheckStates = showCheckBoxes ? new ArrayList<Boolean>() : null;
mSaveKeyringParcel = saveKeyringParcel;
+ mShowStatusImages = showStatusImages;
}
public UserAttributesAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) {
@@ -161,12 +166,17 @@ public class UserAttributesAdapter extends CursorAdapter implements AdapterView.
vVerifiedLayout.setVisibility(View.GONE);
} else {
vEditImage.setVisibility(View.GONE);
- vVerifiedLayout.setVisibility(View.VISIBLE);
+
+ if (mShowStatusImages) {
+ vVerifiedLayout.setVisibility(View.VISIBLE);
+ } else {
+ vVerifiedLayout.setVisibility(View.GONE);
+ }
}
if (isRevoked) {
// set revocation icon (can this even be primary?)
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_REVOKED, true);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
// disable revoked user ids
vName.setEnabled(false);
@@ -188,13 +198,13 @@ public class UserAttributesAdapter extends CursorAdapter implements AdapterView.
int isVerified = cursor.getInt(INDEX_VERIFIED);
switch (isVerified) {
case Certs.VERIFIED_SECRET:
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_VERIFIED, false);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
break;
case Certs.VERIFIED_SELF:
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_UNVERIFIED, false);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
break;
default:
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_INVALID, false);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_INVALID, KeyFormattingUtils.DEFAULT_COLOR);
break;
}
}
@@ -225,7 +235,7 @@ public class UserAttributesAdapter extends CursorAdapter implements AdapterView.
}
public ArrayList<String> getSelectedUserIds() {
- ArrayList<String> result = new ArrayList<String>();
+ ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < mCheckStates.size(); i++) {
if (mCheckStates.get(i)) {
mCursor.moveToPosition(i);
@@ -267,7 +277,7 @@ public class UserAttributesAdapter extends CursorAdapter implements AdapterView.
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
- View view = mInflater.inflate(R.layout.view_key_user_id_item, null);
+ View view = mInflater.inflate(R.layout.view_key_adv_user_id_item, null);
// only need to do this once ever, since mShowCheckBoxes is final
view.findViewById(R.id.user_id_item_check_box).setVisibility(mCheckStates != null ? View.VISIBLE : View.GONE);
return view;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
index 4c0e7a492..01218a4e4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
@@ -64,7 +64,7 @@ public class UserIdsAddedAdapter extends ArrayAdapter<String> {
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// Not recycled, inflate a new view
- convertView = mInflater.inflate(R.layout.view_key_user_id_item, null);
+ convertView = mInflater.inflate(R.layout.view_key_adv_user_id_item, null);
final ViewHolder holder = new ViewHolder();
holder.vAddress = (TextView) convertView.findViewById(R.id.user_id_item_address);
holder.vName = (TextView) convertView.findViewById(R.id.user_id_item_name);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
index b4119a5eb..d5376cbdc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
@@ -145,20 +145,20 @@ public class AddSubkeyDialogFragment extends DialogFragment {
}
{
- ArrayList<Choice<Algorithm>> choices = new ArrayList<Choice<Algorithm>>();
- choices.add(new Choice<Algorithm>(Algorithm.DSA, getResources().getString(
+ ArrayList<Choice<Algorithm>> choices = new ArrayList<>();
+ choices.add(new Choice<>(Algorithm.DSA, getResources().getString(
R.string.dsa)));
if (!mWillBeMasterKey) {
- choices.add(new Choice<Algorithm>(Algorithm.ELGAMAL, getResources().getString(
+ choices.add(new Choice<>(Algorithm.ELGAMAL, getResources().getString(
R.string.elgamal)));
}
- choices.add(new Choice<Algorithm>(Algorithm.RSA, getResources().getString(
+ choices.add(new Choice<>(Algorithm.RSA, getResources().getString(
R.string.rsa)));
- choices.add(new Choice<Algorithm>(Algorithm.ECDSA, getResources().getString(
+ choices.add(new Choice<>(Algorithm.ECDSA, getResources().getString(
R.string.ecdsa)));
- choices.add(new Choice<Algorithm>(Algorithm.ECDH, getResources().getString(
+ choices.add(new Choice<>(Algorithm.ECDH, getResources().getString(
R.string.ecdh)));
- ArrayAdapter<Choice<Algorithm>> adapter = new ArrayAdapter<Choice<Algorithm>>(context,
+ ArrayAdapter<Choice<Algorithm>> adapter = new ArrayAdapter<>(context,
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mAlgorithmSpinner.setAdapter(adapter);
@@ -172,20 +172,20 @@ public class AddSubkeyDialogFragment extends DialogFragment {
}
// dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change
- ArrayAdapter<CharSequence> keySizeAdapter = new ArrayAdapter<CharSequence>(context, android.R.layout.simple_spinner_item,
+ ArrayAdapter<CharSequence> keySizeAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item,
new ArrayList<CharSequence>(Arrays.asList(getResources().getStringArray(R.array.rsa_key_size_spinner_values))));
keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mKeySizeSpinner.setAdapter(keySizeAdapter);
mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length
{
- ArrayList<Choice<Curve>> choices = new ArrayList<Choice<Curve>>();
+ ArrayList<Choice<Curve>> choices = new ArrayList<>();
- choices.add(new Choice<Curve>(Curve.NIST_P256, getResources().getString(
+ choices.add(new Choice<>(Curve.NIST_P256, getResources().getString(
R.string.key_curve_nist_p256)));
- choices.add(new Choice<Curve>(Curve.NIST_P384, getResources().getString(
+ choices.add(new Choice<>(Curve.NIST_P384, getResources().getString(
R.string.key_curve_nist_p384)));
- choices.add(new Choice<Curve>(Curve.NIST_P521, getResources().getString(
+ choices.add(new Choice<>(Curve.NIST_P521, getResources().getString(
R.string.key_curve_nist_p521)));
/* @see SaveKeyringParcel
@@ -197,7 +197,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
R.string.key_curve_bp_p512)));
*/
- ArrayAdapter<Choice<Curve>> adapter = new ArrayAdapter<Choice<Curve>>(context,
+ ArrayAdapter<Choice<Curve>> adapter = new ArrayAdapter<>(context,
android.R.layout.simple_spinner_item, choices);
mCurveSpinner.setAdapter(adapter);
// make NIST P-256 the default
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
index 3eef04aa7..094c4d8a9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
@@ -45,8 +45,8 @@ import android.widget.TextView.OnEditorActionListener;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.Log;
import java.util.regex.Matcher;
@@ -85,7 +85,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
String predefinedName = getArguments().getString(ARG_NAME);
- ArrayAdapter<String> autoCompleteEmailAdapter = new ArrayAdapter<String>
+ ArrayAdapter<String> autoCompleteEmailAdapter = new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserEmails(getActivity())
);
@@ -150,7 +150,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA
mName.setThreshold(1); // Start working from first character
mName.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserNames(getActivity())
)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/BadImportKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AdvancedAppSettingsDialogFragment.java
index 19cf27259..d2fa37cf7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/BadImportKeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AdvancedAppSettingsDialogFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
@@ -25,43 +25,48 @@ import android.support.v4.app.FragmentActivity;
import org.sufficientlysecure.keychain.R;
-public class BadImportKeyDialogFragment extends DialogFragment {
- private static final String ARG_BAD_IMPORT = "bad_import";
+public class AdvancedAppSettingsDialogFragment extends DialogFragment {
+ private static final String ARG_PACKAGE_NAME = "package_name";
+ private static final String ARG_SIGNATURE = "signature";
/**
- * Creates a new instance of this Bad Import Key DialogFragment
- *
- * @param bad
- * @return
+ * Creates new instance of this fragment
*/
- public static BadImportKeyDialogFragment newInstance(int bad) {
- BadImportKeyDialogFragment frag = new BadImportKeyDialogFragment();
+ public static AdvancedAppSettingsDialogFragment newInstance(String packageName, String digest) {
+ AdvancedAppSettingsDialogFragment frag = new AdvancedAppSettingsDialogFragment();
Bundle args = new Bundle();
+ args.putString(ARG_PACKAGE_NAME, packageName);
+ args.putString(ARG_SIGNATURE, digest);
- args.putInt(ARG_BAD_IMPORT, bad);
frag.setArguments(args);
-
return frag;
}
+ /**
+ * Creates dialog
+ */
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final FragmentActivity activity = getActivity();
- final int badImport = getArguments().getInt(ARG_BAD_IMPORT);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
- alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
- alert.setTitle(R.string.warning);
- alert.setMessage(activity.getResources()
- .getQuantityString(R.plurals.bad_keys_encountered, badImport, badImport));
- alert.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
+
+ alert.setTitle(R.string.api_settings_advanced);
alert.setCancelable(true);
+ alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dismiss();
+ }
+ });
+
+ String packageName = getArguments().getString(ARG_PACKAGE_NAME);
+ String signature = getArguments().getString(ARG_SIGNATURE);
+
+ alert.setMessage(getString(R.string.api_settings_package_name) + ": " + packageName + "\n\n"
+ + getString(R.string.api_settings_package_signature) + ": " + signature);
+
return alert.show();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
index aa27e8391..d405b1dda 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
@@ -26,13 +26,13 @@ public class CustomAlertDialogBuilder extends AlertDialog.Builder {
int dividerId = dialog.getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
View divider = dialog.findViewById(dividerId);
if (divider != null) {
- divider.setBackgroundColor(dialog.getContext().getResources().getColor(R.color.emphasis));
+ divider.setBackgroundColor(dialog.getContext().getResources().getColor(R.color.header_text));
}
int textViewId = dialog.getContext().getResources().getIdentifier("android:id/alertTitle", null, null);
TextView tv = (TextView) dialog.findViewById(textViewId);
if (tv != null) {
- tv.setTextColor(dialog.getContext().getResources().getColor(R.color.emphasis));
+ tv.setTextColor(dialog.getContext().getResources().getColor(R.color.header_text));
}
return dialog;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
index 42e21cd57..879e3f6da 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.ui.dialog;
import android.app.Dialog;
+import android.content.ContentResolver;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Build;
@@ -30,6 +31,8 @@ import android.widget.Toast;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.FileHelper;
+import java.io.File;
+
public class DeleteFileDialogFragment extends DialogFragment {
private static final String ARG_DELETE_URI = "delete_uri";
@@ -69,21 +72,38 @@ public class DeleteFileDialogFragment extends DialogFragment {
@Override
public void onClick(DialogInterface dialog, int id) {
dismiss();
+ String scheme = deleteUri.getScheme();
- // We can not securely delete Uris, so just use usual delete on them
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) {
+ if(scheme.equals(ContentResolver.SCHEME_FILE)) {
+ if(new File(deleteUri.getPath()).delete()) {
Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show();
return;
}
}
+ else if(scheme.equals(ContentResolver.SCHEME_CONTENT)) {
+ // We can not securely delete Uris, so just use usual delete on them
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) {
+ Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ }
- if (getActivity().getContentResolver().delete(deleteUri, null, null) > 0) {
- Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show();
- return;
+ if (getActivity().getContentResolver().delete(deleteUri, null, null) > 0) {
+ Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ // some Uri's a ContentResolver fails to delete is handled by the java.io.File's delete
+ // via the path of the Uri
+ if(new File(deleteUri.getPath()).delete()) {
+ Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show();
+ return;
+ }
}
- Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed, deleteFilename), Toast.LENGTH_SHORT).show();
+ Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed,
+ deleteFilename), Toast.LENGTH_SHORT).show();
// Note: We can't delete every file...
// If possible we should find out if deletion is possible before even showing the option to do so.
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
index 5b96ea231..802f0c11b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
@@ -33,6 +33,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
@@ -100,14 +101,20 @@ public class DeleteKeyDialogFragment extends DialogFragment {
ProviderHelper.FIELD_TYPE_INTEGER
}
);
- String userId = (String) data.get(KeyRings.USER_ID);
+ String name;
+ String[] mainUserId = KeyRing.splitUserId((String) data.get(KeyRings.USER_ID));
+ if (mainUserId[0] != null) {
+ name = mainUserId[0];
+ } else {
+ name = getString(R.string.user_id_no_name);
+ }
hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1;
// Set message depending on which key it is.
mMainMessage.setText(getString(
hasSecret ? R.string.secret_key_deletion_confirmation
: R.string.public_key_deletetion_confirmation,
- userId
+ name
));
} catch (ProviderHelper.NotFoundException e) {
dismiss();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
index 1cc800b2b..7ac85781f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
@@ -37,9 +37,9 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.ui.util.Notify;
import java.io.File;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java
deleted file mode 100644
index 961f92f03..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui.dialog;
-
-import android.annotation.TargetApi;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.nfc.NfcAdapter;
-import android.os.Build;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.support.v4.app.DialogFragment;
-import android.support.v4.app.FragmentActivity;
-
-import org.sufficientlysecure.htmltextview.HtmlTextView;
-import org.sufficientlysecure.keychain.R;
-
-@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-public class ShareNfcDialogFragment extends DialogFragment {
-
- /**
- * Creates new instance of this fragment
- */
- public static ShareNfcDialogFragment newInstance() {
- ShareNfcDialogFragment frag = new ShareNfcDialogFragment();
-
- return frag;
- }
-
- /**
- * Creates dialog
- */
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final FragmentActivity activity = getActivity();
-
- CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
-
- alert.setTitle(R.string.share_nfc_dialog);
- alert.setCancelable(true);
-
- alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dismiss();
- }
- });
-
- HtmlTextView textView = new HtmlTextView(getActivity());
- textView.setPadding(8, 8, 8, 8);
- alert.setView(textView);
-
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
- textView.setText(getString(R.string.error) + ": "
- + getString(R.string.error_jelly_bean_needed));
- } else {
- // check if NFC Adapter is available
- NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity());
- if (nfcAdapter == null) {
- textView.setText(getString(R.string.error) + ": "
- + getString(R.string.error_nfc_needed));
- } else {
- // nfc works...
- textView.setHtmlFromRawResource(getActivity(), R.raw.nfc_beam_share, true);
-
- alert.setNegativeButton(R.string.menu_beam_preferences,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- Intent intentSettings = new Intent(
- Settings.ACTION_NFCSHARING_SETTINGS);
- startActivity(intentSettings);
- }
- }
- );
- }
- }
-
- return alert.show();
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java
deleted file mode 100644
index edd12ec73..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui.util;
-
-import android.app.Activity;
-import android.support.v7.app.ActionBar;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import org.sufficientlysecure.keychain.R;
-
-public class ActionBarHelper {
-
- /**
- * Sets custom view on ActionBar for Done/Cancel activities
- *
- * @param actionBar
- * @param firstText
- * @param firstDrawableId
- * @param firstOnClickListener
- * @param secondText
- * @param secondDrawableId
- * @param secondOnClickListener
- */
- public static void setTwoButtonView(ActionBar actionBar,
- int firstText, int firstDrawableId, OnClickListener firstOnClickListener,
- int secondText, int secondDrawableId, OnClickListener secondOnClickListener) {
-
- // Inflate the custom action bar view
- final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
- .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
- final View customActionBarView = inflater.inflate(
- R.layout.actionbar_custom_view_done_cancel, null);
-
- TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
- firstTextView.setText(firstText);
- firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
- customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
- firstOnClickListener);
- TextView secondTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text));
- secondTextView.setText(secondText);
- secondTextView.setCompoundDrawablesWithIntrinsicBounds(secondDrawableId, 0, 0, 0);
- customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
- secondOnClickListener);
-
- // Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayShowHomeEnabled(false);
- actionBar.setDisplayShowCustomEnabled(true);
- actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
- }
-
- /**
- * Sets custom view on ActionBar for Done activities
- *
- * @param actionBar
- * @param firstText
- * @param firstOnClickListener
- */
- public static void setOneButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
- OnClickListener firstOnClickListener) {
- // Inflate a "Done" custom action bar view to serve as the "Up" affordance.
- final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
- .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
- final View customActionBarView = inflater
- .inflate(R.layout.actionbar_custom_view_done, null);
-
- TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
- firstTextView.setText(firstText);
- firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
- customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
- firstOnClickListener);
-
- // Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayShowHomeEnabled(false);
- actionBar.setDisplayShowCustomEnabled(true);
- actionBar.setCustomView(customActionBarView);
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java
index 3f84bf490..eb5c3df45 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/FormattingUtils.java
@@ -24,18 +24,12 @@ import android.text.style.StrikethroughSpan;
public class FormattingUtils {
- public static SpannableStringBuilder strikeOutText(CharSequence text) {
- SpannableStringBuilder sb = new SpannableStringBuilder(text);
- sb.setSpan(new StrikethroughSpan(), 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- return sb;
- }
-
public static int dpToPx(Context context, int dp) {
- return (int) ((dp * context.getResources().getDisplayMetrics().density) + 0.5);
+ return (int) ((dp * context.getResources().getDisplayMetrics().density) + 0.5f);
}
public static int pxToDp(Context context, int px) {
- return (int) ((px / context.getResources().getDisplayMetrics().density) + 0.5);
+ return (int) ((px / context.getResources().getDisplayMetrics().density) + 0.5f);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
index bff7d6b27..38ed88b9c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
@@ -377,6 +377,8 @@ public class KeyFormattingUtils {
((int) digest[2] + 256) % 256};
}
+ public static final int DEFAULT_COLOR = -1;
+
public static final int STATE_REVOKED = 1;
public static final int STATE_EXPIRED = 2;
public static final int STATE_VERIFIED = 3;
@@ -393,20 +395,32 @@ public class KeyFormattingUtils {
}
public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText, int state) {
- setStatusImage(context, statusIcon, statusText, state, false);
+ setStatusImage(context, statusIcon, statusText, state, KeyFormattingUtils.DEFAULT_COLOR, false);
+ }
+
+ public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText,
+ int state, int color) {
+ setStatusImage(context, statusIcon, statusText, state, color, false);
}
/**
* Sets status image based on constant
*/
public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText,
- int state, boolean unobtrusive) {
+ int state, int color, boolean big) {
switch (state) {
/** GREEN: everything is good **/
case STATE_VERIFIED: {
- statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_verified_cutout));
- int color = R.color.android_green_light;
+ if (big) {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_96px));
+ } else {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_24px));
+ }
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_green_light;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
@@ -416,8 +430,10 @@ public class KeyFormattingUtils {
}
case STATE_ENCRYPTED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_lock_closed));
- int color = R.color.android_green_light;
+ context.getResources().getDrawable(R.drawable.status_lock_closed_24px));
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_green_light;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
@@ -427,9 +443,16 @@ public class KeyFormattingUtils {
}
/** ORANGE: mostly bad... **/
case STATE_UNVERIFIED: {
- statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout));
- int color = R.color.android_orange_light;
+ if (big) {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_96px));
+ } else {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_24px));
+ }
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_orange_light;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
@@ -439,8 +462,10 @@ public class KeyFormattingUtils {
}
case STATE_UNKNOWN_KEY: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout));
- int color = R.color.android_orange_light;
+ context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24px));
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_orange_light;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
@@ -450,11 +475,15 @@ public class KeyFormattingUtils {
}
/** RED: really bad... **/
case STATE_REVOKED: {
- statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout));
- int color = R.color.android_red_light;
- if (unobtrusive) {
- color = R.color.bg_gray;
+ if (big) {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_96px));
+ } else {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_24px));
+ }
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_red_light;
}
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
@@ -464,11 +493,15 @@ public class KeyFormattingUtils {
break;
}
case STATE_EXPIRED: {
- statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_expired_cutout));
- int color = R.color.android_red_light;
- if (unobtrusive) {
- color = R.color.bg_gray;
+ if (big) {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_96px));
+ } else {
+ statusIcon.setImageDrawable(
+ context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_24px));
+ }
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_red_light;
}
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
@@ -479,8 +512,10 @@ public class KeyFormattingUtils {
}
case STATE_NOT_ENCRYPTED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_lock_open));
- int color = R.color.android_red_light;
+ context.getResources().getDrawable(R.drawable.status_lock_open_24px));
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_red_light;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
@@ -490,8 +525,10 @@ public class KeyFormattingUtils {
}
case STATE_NOT_SIGNED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout));
- int color = R.color.android_red_light;
+ context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24px));
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_red_light;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
@@ -501,8 +538,10 @@ public class KeyFormattingUtils {
}
case STATE_INVALID: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout));
- int color = R.color.android_red_light;
+ context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24px));
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.android_red_light;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
@@ -513,8 +552,10 @@ public class KeyFormattingUtils {
/** special **/
case STATE_UNAVAILABLE: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout));
- int color = R.color.bg_gray;
+ context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24px));
+ if (color == KeyFormattingUtils.DEFAULT_COLOR) {
+ color = R.color.bg_gray;
+ }
statusIcon.setColorFilter(context.getResources().getColor(color),
PorterDuff.Mode.SRC_IN);
if (statusText != null) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
index 551ac039d..3bc29edb6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
@@ -20,46 +20,135 @@ package org.sufficientlysecure.keychain.ui.util;
import android.app.Activity;
import android.content.res.Resources;
-import com.github.johnpersano.supertoasts.SuperCardToast;
-import com.github.johnpersano.supertoasts.SuperToast;
+import com.nispok.snackbar.Snackbar;
+import com.nispok.snackbar.Snackbar.SnackbarDuration;
+import com.nispok.snackbar.SnackbarManager;
+import com.nispok.snackbar.enums.SnackbarType;
+import com.nispok.snackbar.listeners.ActionClickListener;
+import com.nispok.snackbar.listeners.EventListenerAdapter;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.FabContainer;
/**
- * @author danielhass
* Notify wrapper which allows a more easy use of different notification libraries
*/
public class Notify {
public static enum Style {OK, WARN, INFO, ERROR}
+ public static final int LENGTH_INDEFINITE = 0;
+ public static final int LENGTH_LONG = 3500;
+
/**
* Shows a simple in-layout notification with the CharSequence given as parameter
- * @param activity
* @param text Text to show
* @param style Notification styling
*/
- public static void showNotify(Activity activity, CharSequence text, Style style) {
+ public static void showNotify(final Activity activity, CharSequence text, Style style) {
+
+ Snackbar bar = getSnackbar(activity)
+ .text(text);
+
+ switch (style) {
+ case OK:
+ break;
+ case WARN:
+ bar.textColor(activity.getResources().getColor(R.color.android_orange_light));
+ break;
+ case ERROR:
+ bar.textColor(activity.getResources().getColor(R.color.android_red_light));
+ break;
+ }
+
+ SnackbarManager.show(bar);
+
+ }
+
+ public static Showable createNotify (Activity activity, int resId, int duration, Style style) {
+ final Snackbar bar = getSnackbar(activity)
+ .text(resId);
+
+ if (duration == LENGTH_INDEFINITE) {
+ bar.duration(SnackbarDuration.LENGTH_INDEFINITE);
+ } else {
+ bar.duration(duration);
+ }
+
+ switch (style) {
+ case OK:
+ bar.actionColor(activity.getResources().getColor(R.color.android_green_light));
+ break;
+ case WARN:
+ bar.textColor(activity.getResources().getColor(R.color.android_orange_light));
+ break;
+ case ERROR:
+ bar.textColor(activity.getResources().getColor(R.color.android_red_light));
+ break;
+ }
- SuperCardToast st = new SuperCardToast(activity);
- st.setText(text);
- st.setDuration(SuperToast.Duration.MEDIUM);
- switch (style){
+ return new Showable () {
+ @Override
+ public void show() {
+ SnackbarManager.show(bar);
+ }
+ };
+ }
+
+ public static Showable createNotify(Activity activity, int resId, int duration, Style style,
+ final ActionListener listener, int resIdAction) {
+ return createNotify(activity, activity.getString(resId), duration, style, listener, resIdAction);
+ }
+
+ public static Showable createNotify(Activity activity, String msg, int duration, Style style) {
+ return createNotify(activity, msg, duration, style, null, 0);
+ }
+
+ public static Showable createNotify(Activity activity, String msg, int duration, Style style,
+ final ActionListener listener, int resIdAction) {
+
+ final Snackbar bar = getSnackbar(activity)
+ .text(msg);
+
+ if (listener != null) {
+ bar.actionLabel(resIdAction);
+ bar.actionListener(new ActionClickListener() {
+ @Override
+ public void onActionClicked(Snackbar snackbar) {
+ listener.onAction();
+ }
+ });
+ }
+
+ if (duration == LENGTH_INDEFINITE) {
+ bar.duration(SnackbarDuration.LENGTH_INDEFINITE);
+ } else {
+ bar.duration(duration);
+ }
+
+ switch (style) {
case OK:
- st.setBackground(SuperToast.Background.GREEN);
+ bar.actionColor(activity.getResources().getColor(R.color.android_green_light));
break;
case WARN:
- st.setBackground(SuperToast.Background.ORANGE);
+ bar.textColor(activity.getResources().getColor(R.color.android_orange_light));
break;
case ERROR:
- st.setBackground(SuperToast.Background.RED);
+ bar.textColor(activity.getResources().getColor(R.color.android_red_light));
break;
}
- st.show();
+
+ return new Showable () {
+ @Override
+ public void show() {
+ SnackbarManager.show(bar);
+ }
+ };
}
/**
* Shows a simple in-layout notification with the resource text from given id
- * @param activity
* @param resId ResourceId of notification text
* @param style Notification styling
* @throws Resources.NotFoundException
@@ -67,4 +156,36 @@ public class Notify {
public static void showNotify(Activity activity, int resId, Style style) throws Resources.NotFoundException {
showNotify(activity, activity.getResources().getText(resId), style);
}
+
+ private static Snackbar getSnackbar(final Activity activity) {
+ Snackbar bar = Snackbar.with(activity)
+ .type(SnackbarType.MULTI_LINE)
+ .duration(SnackbarDuration.LENGTH_LONG);
+
+ if (activity instanceof FabContainer) {
+ bar.eventListener(new EventListenerAdapter() {
+ @Override
+ public void onShow(Snackbar snackbar) {
+ ((FabContainer) activity).fabMoveUp(snackbar.getHeight());
+ }
+
+ @Override
+ public void onDismiss(Snackbar snackbar) {
+ ((FabContainer) activity).fabRestorePosition();
+ }
+ });
+ }
+ return bar;
+ }
+
+ public interface Showable {
+ public void show();
+
+ }
+
+ public interface ActionListener {
+ public void onAction();
+
+ }
+
} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java
index 36f38045f..b8d4ea7d2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java
@@ -47,7 +47,7 @@ public class QrCodeUtils {
*/
public static Bitmap getQRCodeBitmap(final String input, final int size) {
try {
- final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+ final Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
final BitMatrix result = new QRCodeWriter().encode(input, BarcodeFormat.QR_CODE, size,
size, hints);
@@ -59,7 +59,7 @@ public class QrCodeUtils {
for (int y = 0; y < height; y++) {
final int offset = y * width;
for (int x = 0; x < width; x++) {
- pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
+ pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/AspectRatioImageView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/AspectRatioImageView.java
new file mode 100644
index 000000000..0df5ba5e8
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/AspectRatioImageView.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import org.sufficientlysecure.keychain.R;
+
+/**
+ * Maintains an aspect ratio based on either width or height. Disabled by default.
+ *
+ * from https://gist.github.com/JakeWharton/2856179
+ */
+public class AspectRatioImageView extends ImageView {
+ // NOTE: These must be kept in sync with the AspectRatioImageView attributes in attrs.xml.
+ public static final int MEASUREMENT_WIDTH = 0;
+ public static final int MEASUREMENT_HEIGHT = 1;
+
+ private static final float DEFAULT_ASPECT_RATIO = 1f;
+ private static final boolean DEFAULT_ASPECT_RATIO_ENABLED = false;
+ private static final int DEFAULT_DOMINANT_MEASUREMENT = MEASUREMENT_WIDTH;
+
+ private float aspectRatio;
+ private boolean aspectRatioEnabled;
+ private int dominantMeasurement;
+
+ public AspectRatioImageView(Context context) {
+ this(context, null);
+ }
+
+ public AspectRatioImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AspectRatioImageView);
+ aspectRatio = a.getFloat(R.styleable.AspectRatioImageView_aspectRatio, DEFAULT_ASPECT_RATIO);
+ aspectRatioEnabled = a.getBoolean(R.styleable.AspectRatioImageView_aspectRatioEnabled,
+ DEFAULT_ASPECT_RATIO_ENABLED);
+ dominantMeasurement = a.getInt(R.styleable.AspectRatioImageView_dominantMeasurement,
+ DEFAULT_DOMINANT_MEASUREMENT);
+ a.recycle();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (!aspectRatioEnabled) return;
+
+ int newWidth;
+ int newHeight;
+ switch (dominantMeasurement) {
+ case MEASUREMENT_WIDTH:
+ newWidth = getMeasuredWidth();
+ newHeight = (int) (newWidth * aspectRatio);
+ break;
+
+ case MEASUREMENT_HEIGHT:
+ newHeight = getMeasuredHeight();
+ newWidth = (int) (newHeight * aspectRatio);
+ break;
+
+ default:
+ throw new IllegalStateException("Unknown measurement with ID " + dominantMeasurement);
+ }
+
+ setMeasuredDimension(newWidth, newHeight);
+ }
+
+ /**
+ * Get the aspect ratio for this image view.
+ */
+ public float getAspectRatio() {
+ return aspectRatio;
+ }
+
+ /**
+ * Set the aspect ratio for this image view. This will update the view instantly.
+ */
+ public void setAspectRatio(float aspectRatio) {
+ this.aspectRatio = aspectRatio;
+ if (aspectRatioEnabled) {
+ requestLayout();
+ }
+ }
+
+ /**
+ * Get whether or not forcing the aspect ratio is enabled.
+ */
+ public boolean getAspectRatioEnabled() {
+ return aspectRatioEnabled;
+ }
+
+ /**
+ * set whether or not forcing the aspect ratio is enabled. This will re-layout the view.
+ */
+ public void setAspectRatioEnabled(boolean aspectRatioEnabled) {
+ this.aspectRatioEnabled = aspectRatioEnabled;
+ requestLayout();
+ }
+
+ /**
+ * Get the dominant measurement for the aspect ratio.
+ */
+ public int getDominantMeasurement() {
+ return dominantMeasurement;
+ }
+
+ /**
+ * Set the dominant measurement for the aspect ratio.
+ *
+ * @see #MEASUREMENT_WIDTH
+ * @see #MEASUREMENT_HEIGHT
+ */
+ public void setDominantMeasurement(int dominantMeasurement) {
+ if (dominantMeasurement != MEASUREMENT_HEIGHT && dominantMeasurement != MEASUREMENT_WIDTH) {
+ throw new IllegalArgumentException("Invalid measurement type.");
+ }
+ this.dominantMeasurement = dominantMeasurement;
+ requestLayout();
+ }
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
index 14f42eb04..6d0e6556f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
@@ -27,9 +27,9 @@ import android.util.AttributeSet;
import android.widget.ImageView;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
-import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
public class CertifyKeySpinner extends KeySpinner {
@@ -86,32 +86,33 @@ public class CertifyKeySpinner extends KeySpinner {
super.onLoadFinished(loader, data);
if (loader.getId() == LOADER_ID) {
+ mIndexHasCertify = data.getColumnIndex(KeychainContract.KeyRings.HAS_CERTIFY);
+ mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED);
+ mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED);
+
// If there is only one choice, pick it by default
if (mAdapter.getCount() == 2) {
// preselect if key can certify
- if (data.moveToPosition(1) && !data.isNull(mIndexHasCertify)) {
+ if (data.moveToPosition(0) && !data.isNull(mIndexHasCertify)) {
setSelection(1);
}
}
- mIndexHasCertify = data.getColumnIndex(KeychainContract.KeyRings.HAS_CERTIFY);
- mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED);
- mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED);
}
}
@Override
boolean setStatus(Context context, Cursor cursor, ImageView statusView) {
if (cursor.getInt(mIndexIsRevoked) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_REVOKED, true);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
return false;
}
if (cursor.getInt(mIndexIsExpired) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_EXPIRED, true);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
return false;
}
// don't invalidate the "None" entry, which is also null!
if (cursor.getPosition() != 0 && cursor.isNull(mIndexHasCertify)) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_UNAVAILABLE, true);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_UNAVAILABLE, R.color.bg_gray);
return false;
}
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 e03a14989..f05f5f96b 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
@@ -28,7 +28,6 @@ import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
-import android.text.SpannableStringBuilder;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,14 +41,13 @@ import com.tokenautocomplete.TokenCompleteTextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
@@ -165,7 +163,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView {
setAdapter(new EncryptKeyAdapter(Collections.<EncryptionKey>emptyList()));
return;
}
- ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey>();
+ ArrayList<EncryptionKey> keys = new ArrayList<>();
while (cursor.moveToNext()) {
try {
EncryptionKey key = new EncryptionKey(cursor);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java
index b456b61ab..34e7b639a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java
@@ -33,17 +33,16 @@ import org.sufficientlysecure.keychain.R;
/**
* Class representing a LinearLayout that can fold and hide it's content when pressed
* To use just add the following to your xml layout
-
- <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- custom:foldedLabel="@string/TEXT_TO_DISPLAY_WHEN_FOLDED"
- custom:unFoldedLabel="@string/TEXT_TO_DISPLAY_WHEN_UNFOLDED">
-
- <include layout="@layout/ELEMENTS_TO_BE_FOLDED"/>
-
- </org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout>
-
+ * <p/>
+ * <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout
+ * android:layout_width="wrap_content"
+ * android:layout_height="wrap_content"
+ * custom:foldedLabel="@string/TEXT_TO_DISPLAY_WHEN_FOLDED"
+ * custom:unFoldedLabel="@string/TEXT_TO_DISPLAY_WHEN_UNFOLDED">
+ * <p/>
+ * <include layout="@layout/ELEMENTS_TO_BE_FOLDED"/>
+ * <p/>
+ * </org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout>
*/
public class FoldableLinearLayout extends LinearLayout {
@@ -75,6 +74,7 @@ public class FoldableLinearLayout extends LinearLayout {
/**
* Load given attributes to inner variables,
+ *
* @param context
* @param attrs
*/
@@ -87,8 +87,8 @@ public class FoldableLinearLayout extends LinearLayout {
a.recycle();
}
// If any attribute isn't found then set a default one
- mFoldedLabel = (mFoldedLabel == null) ? context.getString(R.id.none) : mFoldedLabel;
- mUnFoldedLabel = (mUnFoldedLabel == null) ? context.getString(R.id.none) : mUnFoldedLabel;
+ mFoldedLabel = (mFoldedLabel == null) ? context.getString(R.string.none) : mFoldedLabel;
+ mUnFoldedLabel = (mUnFoldedLabel == null) ? context.getString(R.string.none) : mUnFoldedLabel;
}
@Override
@@ -138,7 +138,7 @@ public class FoldableLinearLayout extends LinearLayout {
private void initialiseInnerViews() {
mFoldableIcon = (ImageView) mFoldableLayout.findViewById(R.id.foldableIcon);
- mFoldableIcon.setImageResource(R.drawable.ic_action_expand);
+ mFoldableIcon.setImageResource(R.drawable.ic_expand_more_black_24dp);
mFoldableTextView = (TextView) mFoldableLayout.findViewById(R.id.foldableText);
mFoldableTextView.setText(mFoldedLabel);
@@ -151,7 +151,7 @@ public class FoldableLinearLayout extends LinearLayout {
public void onClick(View view) {
mFolded = !mFolded;
if (mFolded) {
- mFoldableIcon.setImageResource(R.drawable.ic_action_collapse);
+ mFoldableIcon.setImageResource(R.drawable.ic_expand_less_black_24dp);
mFoldableContainer.setVisibility(View.VISIBLE);
AlphaAnimation animation = new AlphaAnimation(0f, 1f);
animation.setDuration(mShortAnimationDuration);
@@ -159,12 +159,13 @@ public class FoldableLinearLayout extends LinearLayout {
mFoldableTextView.setText(mUnFoldedLabel);
} else {
- mFoldableIcon.setImageResource(R.drawable.ic_action_expand);
+ mFoldableIcon.setImageResource(R.drawable.ic_expand_more_black_24dp);
AlphaAnimation animation = new AlphaAnimation(1f, 0f);
animation.setDuration(mShortAnimationDuration);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
- public void onAnimationStart(Animation animation) { }
+ public void onAnimationStart(Animation animation) {
+ }
@Override
public void onAnimationEnd(Animation animation) {
@@ -173,7 +174,8 @@ public class FoldableLinearLayout extends LinearLayout {
}
@Override
- public void onAnimationRepeat(Animation animation) { }
+ public void onAnimationRepeat(Animation animation) {
+ }
});
mFoldableContainer.startAnimation(animation);
mFoldableTextView.setText(mFoldedLabel);
@@ -185,6 +187,7 @@ public class FoldableLinearLayout extends LinearLayout {
/**
* Adds provided child view to foldableContainer View
+ *
* @param child
*/
@Override
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 7ec6ffe95..c8eceea50 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,24 +24,28 @@ 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.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
-import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
-public abstract class KeySpinner extends Spinner implements LoaderManager.LoaderCallbacks<Cursor> {
+/**
+ * Use TintSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon.
+ * Related: http://stackoverflow.com/a/27713090
+ */
+public abstract class KeySpinner extends TintSpinner implements LoaderManager.LoaderCallbacks<Cursor> {
public interface OnKeyChangedListener {
public void onKeyChanged(long masterKeyId);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java
deleted file mode 100644
index b3c3eb417..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2014 Daniel Albert
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui.widget;
-
-import android.content.Context;
-import android.support.v4.widget.NoScrollableSwipeRefreshLayout;
-import android.util.AttributeSet;
-import android.view.InputDevice;
-import android.view.InputDevice.MotionRange;
-import android.view.MotionEvent;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.util.Log;
-
-import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
-
-public class ListAwareSwipeRefreshLayout extends NoScrollableSwipeRefreshLayout {
-
- private StickyListHeadersListView mStickyListHeadersListView = null;
- private boolean mIsLocked = false;
-
- /**
- * Constructors
- */
- public ListAwareSwipeRefreshLayout(Context context) {
- super(context);
- }
-
- public ListAwareSwipeRefreshLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Getters / Setters
- */
- public void setStickyListHeadersListView(StickyListHeadersListView stickyListHeadersListView) {
- mStickyListHeadersListView = stickyListHeadersListView;
- }
-
- public StickyListHeadersListView getStickyListHeadersListView() {
- return mStickyListHeadersListView;
- }
-
- public void setIsLocked(boolean locked) {
- mIsLocked = locked;
- }
-
- public boolean getIsLocked() {
- return mIsLocked;
- }
-
- @Override
- public boolean canChildScrollUp() {
- if (mStickyListHeadersListView == null) {
- return super.canChildScrollUp();
- }
-
- return (mIsLocked || (
- mStickyListHeadersListView.getWrappedList().getChildCount() > 0
- && (mStickyListHeadersListView.getWrappedList().getChildAt(0).getTop() < 0
- || mStickyListHeadersListView.getFirstVisiblePosition() > 0)
- )
- );
- }
-
- /** Called on a touch event, this method exempts a small area in the upper right from pull to
- * refresh handling.
- *
- * If the touch event happens somewhere in the upper right corner of the screen, we return false
- * to indicate that the event was not handled. This ensures events in that area are always
- * handed through to the list scrollbar handle. For all other cases, we pass the message through
- * to the pull to refresh handler.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // The device may be null. This actually happens
- if (event.getDevice() != null) {
- // MotionEvent.AXIS_X is api level 12, for some reason, so we use a constant 0 here
- float ratioX = event.getX() / event.getDevice().getMotionRange(0).getMax();
- float ratioY = event.getY() / event.getDevice().getMotionRange(1).getMax();
- // if this is the upper right corner, don't handle as pull to refresh event
- if (ratioX > 0.85f && ratioY < 0.15f) {
- return false;
- }
- }
- return super.onTouchEvent(event);
- }
-
-} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java
index 59d05a62e..fe91e306e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java
@@ -84,15 +84,15 @@ public class SignKeySpinner extends KeySpinner {
@Override
boolean setStatus(Context context, Cursor cursor, ImageView statusView) {
if (cursor.getInt(mIndexIsRevoked) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_REVOKED, true);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
return false;
}
if (cursor.getInt(mIndexIsExpired) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_EXPIRED, true);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
return false;
}
if (cursor.getInt(mIndexHasSign) == 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_UNAVAILABLE, true);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_UNAVAILABLE, R.color.bg_gray);
return false;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabLayout.java
deleted file mode 100644
index 17471c86c..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabLayout.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.ui.widget;
-
-import android.content.Context;
-import android.graphics.Typeface;
-import android.os.Build;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.HorizontalScrollView;
-import android.widget.TextView;
-
-/**
- * Copied from http://developer.android.com/samples/SlidingTabsColors/index.html
- */
-
-/**
- * To be used with ViewPager to provide a tab indicator component which give constant feedback as to
- * the user's scroll progress.
- * <p/>
- * To use the component, simply add it to your view hierarchy. Then in your
- * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call
- * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for.
- * <p/>
- * The colors can be customized in two ways. The first and simplest is to provide an array of colors
- * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The
- * alternative is via the {@link TabColorizer} interface which provides you complete control over
- * which color is used for any individual position.
- * <p/>
- * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)},
- * providing the layout ID of your custom layout.
- */
-public class SlidingTabLayout extends HorizontalScrollView {
-
- /**
- * Allows complete control over the colors drawn in the tab layout. Set with
- * {@link #setCustomTabColorizer(TabColorizer)}.
- */
- public interface TabColorizer {
-
- /**
- * @return return the color of the indicator used when {@code position} is selected.
- */
- int getIndicatorColor(int position);
-
- /**
- * @return return the color of the divider drawn to the right of {@code position}.
- */
- int getDividerColor(int position);
-
- }
-
- private static final int TITLE_OFFSET_DIPS = 24;
- private static final int TAB_VIEW_PADDING_DIPS = 16;
- private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
-
- private int mTitleOffset;
-
- private int mTabViewLayoutId;
- private int mTabViewTextViewId;
-
- private ViewPager mViewPager;
- private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
-
- private final SlidingTabStrip mTabStrip;
-
- public SlidingTabLayout(Context context) {
- this(context, null);
- }
-
- public SlidingTabLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- // Disable the Scroll Bar
- setHorizontalScrollBarEnabled(false);
- // Make sure that the Tab Strips fills this View
- setFillViewport(true);
-
- mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
-
- mTabStrip = new SlidingTabStrip(context);
- addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- }
-
- /**
- * Set the custom {@link TabColorizer} to be used.
- * <p/>
- * If you only require simple custmisation then you can use
- * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve
- * similar effects.
- */
- public void setCustomTabColorizer(TabColorizer tabColorizer) {
- mTabStrip.setCustomTabColorizer(tabColorizer);
- }
-
- /**
- * Sets the colors to be used for indicating the selected tab. These colors are treated as a
- * circular array. Providing one color will mean that all tabs are indicated with the same color.
- */
- public void setSelectedIndicatorColors(int... colors) {
- mTabStrip.setSelectedIndicatorColors(colors);
- }
-
- /**
- * Sets the colors to be used for tab dividers. These colors are treated as a circular array.
- * Providing one color will mean that all tabs are indicated with the same color.
- */
- public void setDividerColors(int... colors) {
- mTabStrip.setDividerColors(colors);
- }
-
- /**
- * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are
- * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so
- * that the layout can update it's scroll position correctly.
- *
- * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
- */
- public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
- mViewPagerPageChangeListener = listener;
- }
-
- /**
- * Set the custom layout to be inflated for the tab views.
- *
- * @param layoutResId Layout id to be inflated
- * @param textViewId id of the {@link TextView} in the inflated view
- */
- public void setCustomTabView(int layoutResId, int textViewId) {
- mTabViewLayoutId = layoutResId;
- mTabViewTextViewId = textViewId;
- }
-
- /**
- * Sets the associated view pager. Note that the assumption here is that the pager content
- * (number of tabs and tab titles) does not change after this call has been made.
- */
- public void setViewPager(ViewPager viewPager) {
- mTabStrip.removeAllViews();
-
- mViewPager = viewPager;
- if (viewPager != null) {
- viewPager.setOnPageChangeListener(new InternalViewPagerListener());
- populateTabStrip();
- }
- }
-
- /**
- * Create a default view to be used for tabs. This is called if a custom tab view is not set via
- * {@link #setCustomTabView(int, int)}.
- */
- protected TextView createDefaultTabView(Context context) {
- TextView textView = new TextView(context);
- textView.setGravity(Gravity.CENTER);
- textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
- textView.setTypeface(Typeface.DEFAULT_BOLD);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- // If we're running on Honeycomb or newer, then we can use the Theme's
- // selectableItemBackground to ensure that the View has a pressed state
- TypedValue outValue = new TypedValue();
- getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
- outValue, true);
- textView.setBackgroundResource(outValue.resourceId);
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style
- textView.setAllCaps(true);
- }
-
- int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
- textView.setPadding(padding, padding, padding, padding);
-
- return textView;
- }
-
- private void populateTabStrip() {
- final PagerAdapter adapter = mViewPager.getAdapter();
- final View.OnClickListener tabClickListener = new TabClickListener();
-
- for (int i = 0; i < adapter.getCount(); i++) {
- View tabView = null;
- TextView tabTitleView = null;
-
- if (mTabViewLayoutId != 0) {
- // If there is a custom tab view layout id set, try and inflate it
- tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
- false);
- tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
- }
-
- if (tabView == null) {
- tabView = createDefaultTabView(getContext());
- }
-
- if (tabTitleView == null && TextView.class.isInstance(tabView)) {
- tabTitleView = (TextView) tabView;
- }
-
- tabTitleView.setText(adapter.getPageTitle(i));
- tabView.setOnClickListener(tabClickListener);
-
- mTabStrip.addView(tabView);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- if (mViewPager != null) {
- scrollToTab(mViewPager.getCurrentItem(), 0);
- }
- }
-
- private void scrollToTab(int tabIndex, int positionOffset) {
- final int tabStripChildCount = mTabStrip.getChildCount();
- if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
- return;
- }
-
- View selectedChild = mTabStrip.getChildAt(tabIndex);
- if (selectedChild != null) {
- int targetScrollX = selectedChild.getLeft() + positionOffset;
-
- if (tabIndex > 0 || positionOffset > 0) {
- // If we're not at the first child and are mid-scroll, make sure we obey the offset
- targetScrollX -= mTitleOffset;
- }
-
- scrollTo(targetScrollX, 0);
- }
- }
-
- private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
- private int mScrollState;
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- int tabStripChildCount = mTabStrip.getChildCount();
- if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
- return;
- }
-
- mTabStrip.onViewPagerPageChanged(position, positionOffset);
-
- View selectedTitle = mTabStrip.getChildAt(position);
- int extraOffset = (selectedTitle != null)
- ? (int) (positionOffset * selectedTitle.getWidth())
- : 0;
- scrollToTab(position, extraOffset);
-
- if (mViewPagerPageChangeListener != null) {
- mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
- positionOffsetPixels);
- }
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- mScrollState = state;
-
- if (mViewPagerPageChangeListener != null) {
- mViewPagerPageChangeListener.onPageScrollStateChanged(state);
- }
- }
-
- @Override
- public void onPageSelected(int position) {
- if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
- mTabStrip.onViewPagerPageChanged(position, 0f);
- scrollToTab(position, 0);
- }
-
- if (mViewPagerPageChangeListener != null) {
- mViewPagerPageChangeListener.onPageSelected(position);
- }
- }
-
- }
-
- private class TabClickListener implements View.OnClickListener {
- @Override
- public void onClick(View v) {
- for (int i = 0; i < mTabStrip.getChildCount(); i++) {
- if (v == mTabStrip.getChildAt(i)) {
- mViewPager.setCurrentItem(i);
- return;
- }
- }
- }
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabStrip.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabStrip.java
deleted file mode 100644
index 4c41e12c5..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SlidingTabStrip.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.ui.widget;
-
-import android.R;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.View;
-import android.widget.LinearLayout;
-
-/**
- * Copied from http://developer.android.com/samples/SlidingTabsColors/index.html
- */
-class SlidingTabStrip extends LinearLayout {
-
- private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2;
- private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
- private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8;
- private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFFAA66CC;
-
- private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1;
- private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20;
- private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f;
-
- private final int mBottomBorderThickness;
- private final Paint mBottomBorderPaint;
-
- private final int mSelectedIndicatorThickness;
- private final Paint mSelectedIndicatorPaint;
-
- private final int mDefaultBottomBorderColor;
-
- private final Paint mDividerPaint;
- private final float mDividerHeight;
-
- private int mSelectedPosition;
- private float mSelectionOffset;
-
- private SlidingTabLayout.TabColorizer mCustomTabColorizer;
- private final SimpleTabColorizer mDefaultTabColorizer;
-
- SlidingTabStrip(Context context) {
- this(context, null);
- }
-
- SlidingTabStrip(Context context, AttributeSet attrs) {
- super(context, attrs);
- setWillNotDraw(false);
-
- final float density = getResources().getDisplayMetrics().density;
-
- TypedValue outValue = new TypedValue();
- context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);
- final int themeForegroundColor = outValue.data;
-
- mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
- DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
-
- mDefaultTabColorizer = new SimpleTabColorizer();
- mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);
- mDefaultTabColorizer.setDividerColors(setColorAlpha(themeForegroundColor,
- DEFAULT_DIVIDER_COLOR_ALPHA));
-
- mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
- mBottomBorderPaint = new Paint();
- mBottomBorderPaint.setColor(mDefaultBottomBorderColor);
-
- mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
- mSelectedIndicatorPaint = new Paint();
-
- mDividerHeight = DEFAULT_DIVIDER_HEIGHT;
- mDividerPaint = new Paint();
- mDividerPaint.setStrokeWidth((int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density));
- }
-
- void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
- mCustomTabColorizer = customTabColorizer;
- invalidate();
- }
-
- void setSelectedIndicatorColors(int... colors) {
- // Make sure that the custom colorizer is removed
- mCustomTabColorizer = null;
- mDefaultTabColorizer.setIndicatorColors(colors);
- invalidate();
- }
-
- void setDividerColors(int... colors) {
- // Make sure that the custom colorizer is removed
- mCustomTabColorizer = null;
- mDefaultTabColorizer.setDividerColors(colors);
- invalidate();
- }
-
- void onViewPagerPageChanged(int position, float positionOffset) {
- mSelectedPosition = position;
- mSelectionOffset = positionOffset;
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- final int height = getHeight();
- final int childCount = getChildCount();
- final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height);
- final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
- ? mCustomTabColorizer
- : mDefaultTabColorizer;
-
- // Thick colored underline below the current selection
- if (childCount > 0) {
- View selectedTitle = getChildAt(mSelectedPosition);
- int left = selectedTitle.getLeft();
- int right = selectedTitle.getRight();
- int color = tabColorizer.getIndicatorColor(mSelectedPosition);
-
- if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
- int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
- if (color != nextColor) {
- color = blendColors(nextColor, color, mSelectionOffset);
- }
-
- // Draw the selection partway between the tabs
- View nextTitle = getChildAt(mSelectedPosition + 1);
- left = (int) (mSelectionOffset * nextTitle.getLeft() +
- (1.0f - mSelectionOffset) * left);
- right = (int) (mSelectionOffset * nextTitle.getRight() +
- (1.0f - mSelectionOffset) * right);
- }
-
- mSelectedIndicatorPaint.setColor(color);
-
- canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
- height, mSelectedIndicatorPaint);
- }
-
- // Thin underline along the entire bottom edge
- canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);
-
- // Vertical separators between the titles
- int separatorTop = (height - dividerHeightPx) / 2;
- for (int i = 0; i < childCount - 1; i++) {
- View child = getChildAt(i);
- mDividerPaint.setColor(tabColorizer.getDividerColor(i));
- canvas.drawLine(child.getRight(), separatorTop, child.getRight(),
- separatorTop + dividerHeightPx, mDividerPaint);
- }
- }
-
- /**
- * Set the alpha value of the {@code color} to be the given {@code alpha} value.
- */
- private static int setColorAlpha(int color, byte alpha) {
- return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
- }
-
- /**
- * Blend {@code color1} and {@code color2} using the given ratio.
- *
- * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend,
- * 0.0 will return {@code color2}.
- */
- private static int blendColors(int color1, int color2, float ratio) {
- final float inverseRation = 1f - ratio;
- float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
- float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
- float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
- return Color.rgb((int) r, (int) g, (int) b);
- }
-
- private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {
- private int[] mIndicatorColors;
- private int[] mDividerColors;
-
- @Override
- public final int getIndicatorColor(int position) {
- return mIndicatorColors[position % mIndicatorColors.length];
- }
-
- @Override
- public final int getDividerColor(int position) {
- return mDividerColors[position % mDividerColors.length];
- }
-
- void setIndicatorColors(int... colors) {
- mIndicatorColors = colors;
- }
-
- void setDividerColors(int... colors) {
- mDividerColors = colors;
- }
- }
-} \ No newline at end of file